Revision: 506
http://www.exim.org/viewvc/pcre2?view=rev&revision=506
Author: ph10
Date: 2016-04-01 10:15:38 +0100 (Fri, 01 Apr 2016)
Log Message:
-----------
pcre2grep: fix \r\r\n problem for Windows, and give buffer size in error
message.
Modified Paths:
--------------
code/trunk/ChangeLog
code/trunk/src/pcre2grep.c
code/trunk/testdata/grepoutput
Modified: code/trunk/ChangeLog
===================================================================
--- code/trunk/ChangeLog 2016-03-04 08:51:53 UTC (rev 505)
+++ code/trunk/ChangeLog 2016-04-01 09:15:38 UTC (rev 506)
@@ -89,7 +89,15 @@
19. Applied Chris Wilson's patch (Bugzilla #1681) to CMakeLists.txt for MSVC
static compilation.
+20. Updated pcre2grep to set stdout as binary when run under Windows, so as not
+to convert \r\n at the ends of reflected lines into \r\r\n. This required
+ensuring that other output that is written to stdout (e.g. file names) uses the
+appropriate line terminator: \r\n for Windows, \n otherwise.
+21. When a line is too long for pcre2grep's internal buffer, show the maximum
+length in the error message.
+
+
Version 10.21 12-January-2016
-----------------------------
Modified: code/trunk/src/pcre2grep.c
===================================================================
--- code/trunk/src/pcre2grep.c 2016-03-04 08:51:53 UTC (rev 505)
+++ code/trunk/src/pcre2grep.c 2016-04-01 09:15:38 UTC (rev 506)
@@ -121,8 +121,19 @@
#define FWRITE(a,b,c,d) if (fwrite(a,b,c,d)) {}
+/* Under Windows, we have to set stdout to be binary, so that it does not
+convert \r\n at the ends of output lines to \r\r\n. However, that means that
+any messages written to stdout must have \r\n as their line terminator. This is
+handled by using STDOUT_NL as the newline string. */
+#if defined(_WIN32) || defined(WIN32)
+#define STDOUT_NL "\r\n"
+#else
+#define STDOUT_NL "\n"
+#endif
+
+
/*************************************************
* Global variables *
*************************************************/
@@ -885,27 +896,27 @@
{
option_item *op;
-printf("Usage: pcre2grep [OPTION]... [PATTERN] [FILE1 FILE2 ...]\n");
-printf("Search for PATTERN in each FILE or standard input.\n");
-printf("PATTERN must be present if neither -e nor -f is used.\n");
-printf("\"-\" can be used as a file name to mean STDIN.\n");
+printf("Usage: pcre2grep [OPTION]... [PATTERN] [FILE1 FILE2 ...]" STDOUT_NL);
+printf("Search for PATTERN in each FILE or standard input." STDOUT_NL);
+printf("PATTERN must be present if neither -e nor -f is used." STDOUT_NL);
+printf("\"-\" can be used as a file name to mean STDIN." STDOUT_NL);
#ifdef SUPPORT_LIBZ
-printf("Files whose names end in .gz are read using zlib.\n");
+printf("Files whose names end in .gz are read using zlib." STDOUT_NL);
#endif
#ifdef SUPPORT_LIBBZ2
-printf("Files whose names end in .bz2 are read using bzlib2.\n");
+printf("Files whose names end in .bz2 are read using bzlib2." STDOUT_NL);
#endif
#if defined SUPPORT_LIBZ || defined SUPPORT_LIBBZ2
-printf("Other files and the standard input are read as plain files.\n\n");
+printf("Other files and the standard input are read as plain files." STDOUT_NL STDOUT_NL);
#else
-printf("All files are read as plain files, without any interpretation.\n\n");
+printf("All files are read as plain files, without any interpretation." STDOUT_NL STDOUT_NL);
#endif
-printf("Example: pcre2grep -i 'hello.*world' menu.h main.c\n\n");
-printf("Options:\n");
+printf("Example: pcre2grep -i 'hello.*world' menu.h main.c" STDOUT_NL STDOUT_NL);
+printf("Options:" STDOUT_NL);
for (op = optionlist; op->one_char != 0; op++)
{
@@ -922,17 +933,17 @@
}
if (n < 1) n = 1;
- printf("%.*s%s\n", n, " ", op->help_text);
+ printf("%.*s%s" STDOUT_NL, n, " ", op->help_text);
}
-printf("\nNumbers may be followed by K or M, e.g. --buffer-size=100K.\n");
-printf("The default value for --buffer-size is %d.\n", PCRE2GREP_BUFSIZE);
-printf("When reading patterns or file names from a file, trailing white\n");
-printf("space is removed and blank lines are ignored.\n");
-printf("The maximum size of any pattern is %d bytes.\n", MAXPATLEN);
+printf(STDOUT_NL "Numbers may be followed by K or M, e.g. --buffer-size=100K." STDOUT_NL);
+printf("The default value for --buffer-size is %d." STDOUT_NL, PCRE2GREP_BUFSIZE);
+printf("When reading patterns or file names from a file, trailing white" STDOUT_NL);
+printf("space is removed and blank lines are ignored." STDOUT_NL);
+printf("The maximum size of any pattern is %d bytes." STDOUT_NL, MAXPATLEN);
-printf("\nWith no FILEs, read standard input. If fewer than two FILEs given, assume -h.\n");
-printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble.\n");
+printf(STDOUT_NL "With no FILEs, read standard input. If fewer than two FILEs given, assume -h." STDOUT_NL);
+printf("Exit status is 0 if any matches, 1 if no matches, and 2 if trouble." STDOUT_NL);
}
@@ -1609,10 +1620,12 @@
if (endlinelength == 0 && t == main_buffer + bufsize)
{
fprintf(stderr, "pcre2grep: line %d%s%s is too long for the internal buffer\n"
- "pcre2grep: check the --buffer-size option\n",
+ "pcre2grep: the buffer size is %d\n"
+ "pcre2grep: use the --buffer-size option to change it\n",
linenumber,
(filename == NULL)? "" : " of file ",
- (filename == NULL)? "" : filename);
+ (filename == NULL)? "" : filename,
+ bufthird);
return 2;
}
@@ -1705,7 +1718,7 @@
else if (binary)
{
- fprintf(stdout, "Binary file %s matches\n", filename);
+ fprintf(stdout, "Binary file %s matches" STDOUT_NL, filename);
return 0;
}
@@ -1714,7 +1727,7 @@
else if (filenames == FN_MATCH_ONLY)
{
- fprintf(stdout, "%s\n", printname);
+ fprintf(stdout, "%s" STDOUT_NL, printname);
return 0;
}
@@ -1739,13 +1752,13 @@
/* Handle --line-offsets */
if (line_offsets)
- fprintf(stdout, "%d,%d\n", (int)(matchptr + offsets[0] - ptr),
+ fprintf(stdout, "%d,%d" STDOUT_NL, (int)(matchptr + offsets[0] - ptr),
(int)(offsets[1] - offsets[0]));
/* Handle --file-offsets */
else if (file_offsets)
- fprintf(stdout, "%d,%d\n",
+ fprintf(stdout, "%d,%d" STDOUT_NL,
(int)(filepos + matchptr + offsets[0] - ptr),
(int)(offsets[1] - offsets[0]));
@@ -1773,7 +1786,8 @@
}
}
- if (printed || printname != NULL || number) fprintf(stdout, "\n");
+ if (printed || printname != NULL || number)
+ fprintf(stdout, STDOUT_NL);
}
/* Prepare to repeat to find the next match. If the pattern contained a
@@ -1838,7 +1852,7 @@
if (hyphenpending)
{
- fprintf(stdout, "--\n");
+ fprintf(stdout, "--" STDOUT_NL);
hyphenpending = FALSE;
hyphenprinted = TRUE;
}
@@ -1859,7 +1873,7 @@
}
if (lastmatchnumber > 0 && p > lastmatchrestart && !hyphenprinted)
- fprintf(stdout, "--\n");
+ fprintf(stdout, "--" STDOUT_NL);
while (p < ptr)
{
@@ -2063,7 +2077,7 @@
if (filenames == FN_NOMATCH_ONLY)
{
- fprintf(stdout, "%s\n", printname);
+ fprintf(stdout, "%s" STDOUT_NL, printname);
return 0;
}
@@ -2075,7 +2089,7 @@
{
if (printname != NULL && filenames != FN_NONE)
fprintf(stdout, "%s:", printname);
- fprintf(stdout, "%d\n", count);
+ fprintf(stdout, "%d" STDOUT_NL, count);
}
}
@@ -2396,7 +2410,7 @@
{
unsigned char buffer[128];
(void)pcre2_config(PCRE2_CONFIG_VERSION, buffer);
- fprintf(stdout, "pcre2grep version %s\n", buffer);
+ fprintf(stdout, "pcre2grep version %s" STDOUT_NL, buffer);
}
pcre2grep_exit(0);
break;
@@ -2623,6 +2637,16 @@
pcre2_jit_stack *jit_stack = NULL;
#endif
+/* In Windows, stdout is set up as a text stream, which means that \n is
+converted to \r\n. This causes output lines that are copied from the input to
+change from ....\r\n to ....\r\r\n, which is not right. We therefore ensure
+that stdout is a binary stream. Note that this means all other output to stdout
+must use STDOUT_NL to terminate lines. */
+
+#if defined(_WIN32) || defined(WIN32)
+setmode(fileno(stdout), O_BINARY);
+#endif
+
/* Set up a default compile and match contexts and a match data block. */
compile_context = pcre2_compile_context_create(NULL);
Modified: code/trunk/testdata/grepoutput
===================================================================
(Binary files differ)