Skip to content

Commit 6bff719

Browse files
committed
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 #2924)
1 parent dbe8869 commit 6bff719

2 files changed

Lines changed: 164 additions & 103 deletions

File tree

src/quickfix.c

Lines changed: 162 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -227,20 +227,173 @@ static struct fmtpattern
227227
{'o', ".\\+"}
228228
};
229229

230+
/*
231+
* Convert an errorformat pattern to a regular expression pattern.
232+
* See fmt_pat definition above for the list of supported patterns.
233+
*/
234+
static char_u *
235+
fmtpat_to_regpat(
236+
char_u *efmp,
237+
efm_T *fmt_ptr,
238+
int idx,
239+
int round,
240+
char_u *ptr,
241+
char_u *errmsg)
242+
{
243+
char_u *srcptr;
244+
245+
if (fmt_ptr->addr[idx])
246+
{
247+
/* Each errorformat pattern can occur only once */
248+
sprintf((char *)errmsg,
249+
_("E372: Too many %%%c in format string"), *efmp);
250+
EMSG(errmsg);
251+
return NULL;
252+
}
253+
if ((idx && idx < 6
254+
&& vim_strchr((char_u *)"DXOPQ", fmt_ptr->prefix) != NULL)
255+
|| (idx == 6
256+
&& vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL))
257+
{
258+
sprintf((char *)errmsg,
259+
_("E373: Unexpected %%%c in format string"), *efmp);
260+
EMSG(errmsg);
261+
return NULL;
262+
}
263+
fmt_ptr->addr[idx] = (char_u)++round;
264+
*ptr++ = '\\';
265+
*ptr++ = '(';
266+
#ifdef BACKSLASH_IN_FILENAME
267+
if (*efmp == 'f')
268+
{
269+
/* Also match "c:" in the file name, even when
270+
* checking for a colon next: "%f:".
271+
* "\%(\a:\)\=" */
272+
STRCPY(ptr, "\\%(\\a:\\)\\=");
273+
ptr += 10;
274+
}
275+
#endif
276+
if (*efmp == 'f' && efmp[1] != NUL)
277+
{
278+
if (efmp[1] != '\\' && efmp[1] != '%')
279+
{
280+
/* A file name may contain spaces, but this isn't
281+
* in "\f". For "%f:%l:%m" there may be a ":" in
282+
* the file name. Use ".\{-1,}x" instead (x is
283+
* the next character), the requirement that :999:
284+
* follows should work. */
285+
STRCPY(ptr, ".\\{-1,}");
286+
ptr += 7;
287+
}
288+
else
289+
{
290+
/* File name followed by '\\' or '%': include as
291+
* many file name chars as possible. */
292+
STRCPY(ptr, "\\f\\+");
293+
ptr += 4;
294+
}
295+
}
296+
else
297+
{
298+
srcptr = (char_u *)fmt_pat[idx].pattern;
299+
while ((*ptr = *srcptr++) != NUL)
300+
++ptr;
301+
}
302+
*ptr++ = '\\';
303+
*ptr++ = ')';
304+
305+
return ptr;
306+
}
307+
308+
/*
309+
* Convert a scanf like format in 'errorformat' to a regular expression.
310+
*/
311+
static char_u *
312+
scanf_fmt_to_regpat(
313+
char_u *efm,
314+
int len,
315+
char_u **pefmp,
316+
char_u *ptr,
317+
char_u *errmsg)
318+
{
319+
char_u *efmp = *pefmp;
320+
321+
if (*++efmp == '[' || *efmp == '\\')
322+
{
323+
if ((*ptr++ = *efmp) == '[') /* %*[^a-z0-9] etc. */
324+
{
325+
if (efmp[1] == '^')
326+
*ptr++ = *++efmp;
327+
if (efmp < efm + len)
328+
{
329+
*ptr++ = *++efmp; /* could be ']' */
330+
while (efmp < efm + len
331+
&& (*ptr++ = *++efmp) != ']')
332+
/* skip */;
333+
if (efmp == efm + len)
334+
{
335+
EMSG(_("E374: Missing ] in format string"));
336+
return NULL;
337+
}
338+
}
339+
}
340+
else if (efmp < efm + len) /* %*\D, %*\s etc. */
341+
*ptr++ = *++efmp;
342+
*ptr++ = '\\';
343+
*ptr++ = '+';
344+
}
345+
else
346+
{
347+
/* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */
348+
sprintf((char *)errmsg,
349+
_("E375: Unsupported %%%c in format string"), *efmp);
350+
EMSG(errmsg);
351+
return NULL;
352+
}
353+
354+
*pefmp = efmp;
355+
356+
return ptr;
357+
}
358+
359+
/*
360+
* Analyze/parse an errorformat prefix.
361+
*/
362+
static int
363+
efm_analyze_prefix(char_u **pefmp, efm_T *fmt_ptr, char_u *errmsg)
364+
{
365+
char_u *efmp = *pefmp;
366+
367+
if (vim_strchr((char_u *)"+-", *efmp) != NULL)
368+
fmt_ptr->flags = *efmp++;
369+
if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
370+
fmt_ptr->prefix = *efmp;
371+
else
372+
{
373+
sprintf((char *)errmsg,
374+
_("E376: Invalid %%%c in format string prefix"), *efmp);
375+
EMSG(errmsg);
376+
return FAIL;
377+
}
378+
379+
*pefmp = efmp;
380+
381+
return OK;
382+
}
383+
230384
/*
231385
* Converts a 'errorformat' string to regular expression pattern
232386
*/
233387
static int
234388
efm_to_regpat(
235389
char_u *efm,
236-
int len,
390+
int len,
237391
efm_T *fmt_ptr,
238392
char_u *regpat,
239393
char_u *errmsg)
240394
{
241395
char_u *ptr;
242396
char_u *efmp;
243-
char_u *srcptr;
244397
int round;
245398
int idx = 0;
246399

@@ -260,102 +413,17 @@ efm_to_regpat(
260413
break;
261414
if (idx < FMT_PATTERNS)
262415
{
263-
if (fmt_ptr->addr[idx])
264-
{
265-
sprintf((char *)errmsg,
266-
_("E372: Too many %%%c in format string"), *efmp);
267-
EMSG(errmsg);
268-
return -1;
269-
}
270-
if ((idx
271-
&& idx < 6
272-
&& vim_strchr((char_u *)"DXOPQ",
273-
fmt_ptr->prefix) != NULL)
274-
|| (idx == 6
275-
&& vim_strchr((char_u *)"OPQ",
276-
fmt_ptr->prefix) == NULL))
277-
{
278-
sprintf((char *)errmsg,
279-
_("E373: Unexpected %%%c in format string"), *efmp);
280-
EMSG(errmsg);
416+
ptr = fmtpat_to_regpat(efmp, fmt_ptr, idx, round, ptr,
417+
errmsg);
418+
if (ptr == NULL)
281419
return -1;
282-
}
283-
fmt_ptr->addr[idx] = (char_u)++round;
284-
*ptr++ = '\\';
285-
*ptr++ = '(';
286-
#ifdef BACKSLASH_IN_FILENAME
287-
if (*efmp == 'f')
288-
{
289-
/* Also match "c:" in the file name, even when
290-
* checking for a colon next: "%f:".
291-
* "\%(\a:\)\=" */
292-
STRCPY(ptr, "\\%(\\a:\\)\\=");
293-
ptr += 10;
294-
}
295-
#endif
296-
if (*efmp == 'f' && efmp[1] != NUL)
297-
{
298-
if (efmp[1] != '\\' && efmp[1] != '%')
299-
{
300-
/* A file name may contain spaces, but this isn't
301-
* in "\f". For "%f:%l:%m" there may be a ":" in
302-
* the file name. Use ".\{-1,}x" instead (x is
303-
* the next character), the requirement that :999:
304-
* follows should work. */
305-
STRCPY(ptr, ".\\{-1,}");
306-
ptr += 7;
307-
}
308-
else
309-
{
310-
/* File name followed by '\\' or '%': include as
311-
* many file name chars as possible. */
312-
STRCPY(ptr, "\\f\\+");
313-
ptr += 4;
314-
}
315-
}
316-
else
317-
{
318-
srcptr = (char_u *)fmt_pat[idx].pattern;
319-
while ((*ptr = *srcptr++) != NUL)
320-
++ptr;
321-
}
322-
*ptr++ = '\\';
323-
*ptr++ = ')';
420+
round++;
324421
}
325422
else if (*efmp == '*')
326423
{
327-
if (*++efmp == '[' || *efmp == '\\')
328-
{
329-
if ((*ptr++ = *efmp) == '[') /* %*[^a-z0-9] etc. */
330-
{
331-
if (efmp[1] == '^')
332-
*ptr++ = *++efmp;
333-
if (efmp < efm + len)
334-
{
335-
*ptr++ = *++efmp; /* could be ']' */
336-
while (efmp < efm + len
337-
&& (*ptr++ = *++efmp) != ']')
338-
/* skip */;
339-
if (efmp == efm + len)
340-
{
341-
EMSG(_("E374: Missing ] in format string"));
342-
return -1;
343-
}
344-
}
345-
}
346-
else if (efmp < efm + len) /* %*\D, %*\s etc. */
347-
*ptr++ = *++efmp;
348-
*ptr++ = '\\';
349-
*ptr++ = '+';
350-
}
351-
else
352-
{
353-
/* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */
354-
sprintf((char *)errmsg,
355-
_("E375: Unsupported %%%c in format string"), *efmp);
356-
EMSG(errmsg);
424+
ptr = scanf_fmt_to_regpat(efm, len, &efmp, ptr, errmsg);
425+
if (ptr == NULL)
357426
return -1;
358-
}
359427
}
360428
else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL)
361429
*ptr++ = *efmp; /* regexp magic characters */
@@ -365,17 +433,8 @@ efm_to_regpat(
365433
fmt_ptr->conthere = TRUE;
366434
else if (efmp == efm + 1) /* analyse prefix */
367435
{
368-
if (vim_strchr((char_u *)"+-", *efmp) != NULL)
369-
fmt_ptr->flags = *efmp++;
370-
if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL)
371-
fmt_ptr->prefix = *efmp;
372-
else
373-
{
374-
sprintf((char *)errmsg,
375-
_("E376: Invalid %%%c in format string prefix"), *efmp);
376-
EMSG(errmsg);
436+
if (efm_analyze_prefix(&efmp, fmt_ptr, errmsg) == FAIL)
377437
return -1;
378-
}
379438
}
380439
else
381440
{

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,8 @@ static char *(features[]) =
761761

762762
static int included_patches[] =
763763
{ /* Add new patch number below this line */
764+
/**/
765+
10,
764766
/**/
765767
9,
766768
/**/

0 commit comments

Comments
 (0)