summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPádraig Brady <P@draigBrady.com>2016-01-08 15:57:06 +0000
committerPádraig Brady <P@draigBrady.com>2016-01-13 10:59:56 +0000
commit8297568ec60103d95a56cf142d534f215086fe2b (patch)
tree0bf21e532d6be6d2e7989a2872b5c24a3a0bd5b0
parent0e46753d7c9519d7378cd3a4e0951a36ac32ffe7 (diff)
downloadcoreutils-8297568ec60103d95a56cf142d534f215086fe2b.tar.xz
paste: add the -z,--zero-terminated option
* doc/coreutils.texi (paste invocation): Reference -z description. * src/paste.c (main): Parameterize the use of '\n'. * tests/misc/paste.pl: Add test cases. * NEWS: Mention the new feature.
-rw-r--r--NEWS2
-rw-r--r--doc/coreutils.texi2
-rw-r--r--src/paste.c26
-rwxr-xr-xtests/misc/paste.pl10
4 files changed, 31 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 27789f761..9f48415de 100644
--- a/NEWS
+++ b/NEWS
@@ -33,7 +33,7 @@ GNU coreutils NEWS -*- outline -*-
** New features
- comm, cut, head, tail now have the -z,--zero-terminated option, and
+ comm, cut, head, paste, tail now have the -z,--zero-terminated option, and
tac --separator accepts an empty argument, to work with NUL delimited items.
dd now summarizes sizes in --human-readable format too, not just --si.
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 157ce0e12..01d76ec2c 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -6004,6 +6004,8 @@ $ paste -d '%_' num2 let3 num2
%c_
@end example
+@optZeroTerminated
+
@end table
@exitstatus
diff --git a/src/paste.c b/src/paste.c
index a5acecd90..bf99fe028 100644
--- a/src/paste.c
+++ b/src/paste.c
@@ -67,10 +67,13 @@ static char *delims;
/* A pointer to the character after the end of 'delims'. */
static char const *delim_end;
+static unsigned char line_delim = '\n';
+
static struct option const longopts[] =
{
{"serial", no_argument, NULL, 's'},
{"delimiters", required_argument, NULL, 'd'},
+ {"zero-terminated", no_argument, NULL, 'z'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -250,7 +253,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
while (chr != EOF)
{
sometodo = true;
- if (chr == '\n')
+ if (chr == line_delim)
break;
xputchar (chr);
chr = getc (fileptr[i]);
@@ -295,7 +298,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
write_error ();
delims_saved = 0;
}
- xputchar ('\n');
+ xputchar (line_delim);
}
continue; /* Next read of files, or exit. */
}
@@ -316,7 +319,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
/* Except for last file, replace last newline with delim. */
if (i + 1 != nfiles)
{
- if (chr != '\n' && chr != EOF)
+ if (chr != line_delim && chr != EOF)
xputchar (chr);
if (*delimptr != EMPTY_DELIM)
xputchar (*delimptr);
@@ -327,7 +330,7 @@ paste_parallel (size_t nfiles, char **fnamptr)
{
/* If the last line of the last file lacks a newline,
print one anyhow. POSIX requires this. */
- char c = (chr == EOF ? '\n' : chr);
+ char c = (chr == EOF ? line_delim : chr);
xputchar (c);
}
}
@@ -386,7 +389,7 @@ paste_serial (size_t nfiles, char **fnamptr)
while ((charnew = getc (fileptr)) != EOF)
{
/* Process the old character. */
- if (charold == '\n')
+ if (charold == line_delim)
{
if (*delimptr != EMPTY_DELIM)
xputchar (*delimptr);
@@ -405,8 +408,8 @@ paste_serial (size_t nfiles, char **fnamptr)
xputchar (charold);
}
- if (charold != '\n')
- xputchar ('\n');
+ if (charold != line_delim)
+ xputchar (line_delim);
if (ferror (fileptr))
{
@@ -447,6 +450,9 @@ each FILE, separated by TABs, to standard output.\n\
-d, --delimiters=LIST reuse characters from LIST instead of TABs\n\
-s, --serial paste one file at a time instead of in parallel\n\
"), stdout);
+ fputs (_("\
+ -z, --zero-terminated line delimiter is NUL, not newline\n\
+"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
/* FIXME: add a couple of examples. */
@@ -473,7 +479,7 @@ main (int argc, char **argv)
have_read_stdin = false;
serial_merge = false;
- while ((optc = getopt_long (argc, argv, "d:s", longopts, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "d:sz", longopts, NULL)) != -1)
{
switch (optc)
{
@@ -486,6 +492,10 @@ main (int argc, char **argv)
serial_merge = true;
break;
+ case 'z':
+ line_delim = '\0';
+ break;
+
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
diff --git a/tests/misc/paste.pl b/tests/misc/paste.pl
index b4409e779..7c9559700 100755
--- a/tests/misc/paste.pl
+++ b/tests/misc/paste.pl
@@ -34,6 +34,11 @@ my @Tests =
['no-nl-3', {IN=>"a"}, {IN=>"b\n"}, {OUT=>"a\tb\n"}],
['no-nl-4', {IN=>"a\n"}, {IN=>"b\n"}, {OUT=>"a\tb\n"}],
+ ['zno-nl-1', '-z', {IN=>"a"}, {IN=>"b"}, {OUT=>"a\tb\0"}],
+ ['zno-nl-2', '-z', {IN=>"a\0"}, {IN=>"b"}, {OUT=>"a\tb\0"}],
+ ['zno-nl-3', '-z', {IN=>"a"}, {IN=>"b\0"}, {OUT=>"a\tb\0"}],
+ ['zno-nl-4', '-z', {IN=>"a\0"}, {IN=>"b\0"}, {OUT=>"a\tb\0"}],
+
# Same as above, but with a two lines in each input file and
# the addition of the -d option to make SPACE be the output delimiter.
['no-nla1', '-d" "', {IN=>"1\na"}, {IN=>"2\nb"}, {OUT=>"1 2\na b\n"}],
@@ -41,6 +46,11 @@ my @Tests =
['no-nla3', '-d" "', {IN=>"1\na"}, {IN=>"2\nb\n"}, {OUT=>"1 2\na b\n"}],
['no-nla4', '-d" "', {IN=>"1\na\n"}, {IN=>"2\nb\n"}, {OUT=>"1 2\na b\n"}],
+ ['zno-nla1', '-zd" "', {IN=>"1\0a"}, {IN=>"2\0b"}, {OUT=>"1 2\0a b\0"}],
+ ['zno-nla2', '-zd" "', {IN=>"1\0a\0"}, {IN=>"2\0b"}, {OUT=>"1 2\0a b\0"}],
+ ['zno-nla3', '-zd" "', {IN=>"1\0a"}, {IN=>"2\0b\0"}, {OUT=>"1 2\0a b\0"}],
+ ['zno-nla4', '-zd" "', {IN=>"1\0a\0"}, {IN=>"2\0b\0"}, {OUT=>"1 2\0a b\0"}],
+
# Specifying a delimiter with a trailing backslash would overrun a
# malloc'd buffer.
['delim-bs1', q!-d'\'!, {IN=>{'a'x50=>''}}, {EXIT => 1},