]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
join: Add the -z, --zero-terminated option
authorAssaf Gordon <assafgordon@gmail.com>
Thu, 14 Feb 2013 20:29:08 +0000 (15:29 -0500)
committerPádraig Brady <P@draigBrady.com>
Thu, 28 Feb 2013 01:49:56 +0000 (01:49 +0000)
* NEWS: Mention join's new option: --zero-terminated (-z).
* src/join.c: Add new option, --zero-terminated (-z), to make
join use the NUL byte as separator/delimiter rather than newline.
(get_line): Use readlinebuffer_delim in place of readlinebuffer.
(main): Handle the new option.
(usage): Describe new option the same way sort does.
* doc/coreutils.texi (join invocation): Describe the new option.
* tests/misc/join.pl: add tests for -z option.

NEWS
doc/coreutils.texi
src/join.c
tests/misc/join.pl

diff --git a/NEWS b/NEWS
index 5a253771a301fcf5247d3b25140e14c8b2305e74..8785bb3333a357c1f7d76be363840f49867e0a2b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,6 +9,12 @@ GNU coreutils NEWS                                    -*- outline -*-
   permissions.
   [This bug was present in "the beginning".]
 
+** New features
+
+  join accepts a new option: --zero-terminated (-z). As with the sort,uniq
+  option of the same name, this makes join consume and produce NUL-terminated
+  lines rather than newline-terminated lines.
+
 
 * Noteworthy changes in release 8.21 (2013-02-14) [stable]
 
index 2c16dc48feeb3e753acb72b09e31f6684d44893c..19ef4651cdcb575a2d064f40e8e6ee0ddd7e1e12 100644 (file)
@@ -6181,6 +6181,8 @@ character is used to delimit the fields.
 Print a line for each unpairable line in file @var{file-number}
 (either @samp{1} or @samp{2}), instead of the normal output.
 
+@zeroTerminatedOption
+
 @end table
 
 @exitstatus
index 11e647cfd3b1fbaf74daa8cea244ec696a658b2e..1da618dc1d5dea7ad2f835f1b22272fa50a8c34f 100644 (file)
@@ -161,6 +161,7 @@ static struct option const longopts[] =
   {"ignore-case", no_argument, NULL, 'i'},
   {"check-order", no_argument, NULL, CHECK_ORDER_OPTION},
   {"nocheck-order", no_argument, NULL, NOCHECK_ORDER_OPTION},
+  {"zero-terminated", no_argument, NULL, 'z'},
   {"header", no_argument, NULL, HEADER_LINE_OPTION},
   {GETOPT_HELP_OPTION_DECL},
   {GETOPT_VERSION_OPTION_DECL},
@@ -177,6 +178,9 @@ static bool ignore_case;
    join them without checking for ordering */
 static bool join_header_lines;
 
+/* The character marking end of line. Default to \n. */
+static char eolchar = '\n';
+
 void
 usage (int status)
 {
@@ -212,6 +216,9 @@ by whitespace.  When FILE1 or FILE2 (not both) is -, read standard input.\n\
   --nocheck-order   do not check that the input is correctly sorted\n\
   --header          treat the first line in each file as field headers,\n\
                       print them without trying to pair them\n\
+"), stdout);
+      fputs (_("\
+  -z, --zero-terminated     end lines with 0 byte, not newline\n\
 "), stdout);
       fputs (HELP_OPTION_DESCRIPTION, stdout);
       fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -445,7 +452,7 @@ get_line (FILE *fp, struct line **linep, int which)
   else
     line = init_linep (linep);
 
-  if (! readlinebuffer (&line->buf, fp))
+  if (! readlinebuffer_delim (&line->buf, fp, eolchar))
     {
       if (ferror (fp))
         error (EXIT_FAILURE, errno, _("read error"));
@@ -614,7 +621,7 @@ prjoin (struct line const *line1, struct line const *line2)
             break;
           putchar (output_separator);
         }
-      putchar ('\n');
+      putchar (eolchar);
     }
   else
     {
@@ -636,7 +643,7 @@ prjoin (struct line const *line1, struct line const *line2)
       prfields (line1, join_field_1, autocount_1);
       prfields (line2, join_field_2, autocount_2);
 
-      putchar ('\n');
+      putchar (eolchar);
     }
 }
 
@@ -1017,7 +1024,7 @@ main (int argc, char **argv)
   issued_disorder_warning[0] = issued_disorder_warning[1] = false;
   check_input_order = CHECK_ORDER_DEFAULT;
 
-  while ((optc = getopt_long (argc, argv, "-a:e:i1:2:j:o:t:v:",
+  while ((optc = getopt_long (argc, argv, "-a:e:i1:2:j:o:t:v:z",
                               longopts, NULL))
          != -1)
     {
@@ -1107,6 +1114,10 @@ main (int argc, char **argv)
           }
           break;
 
+        case 'z':
+          eolchar = 0;
+          break;
+
         case NOCHECK_ORDER_OPTION:
           check_input_order = CHECK_ORDER_DISABLED;
           break;
index 9b93794d9ec8bb88c7c265669e1a12d0ce18ecb9..7e06f1e6c882dde03a4ce8bf2c746eb7036e9d12 100755 (executable)
@@ -275,6 +275,26 @@ my @tv = (
  [ "ID1 Name\n1 A\n", ""],
    "ID1 Name\n1 A\n", 0],
 
+# Zero-terminated lines
+['z1', '-z',
+ ["a\0c\0e\0", "a\0b\0c\0"], "a\0c\0", 0],
+
+# not zero-terminated, but related to the code change:
+#  the old readlinebuffer() auto-added '\n' to the last line.
+#  the new readlinebuffer_delim() does not.
+#  Ensure it doesn't matter.
+['z2', '',
+ ["a\nc\ne\n", "a\nb\nc"], "a\nc\n", 0],
+['z3', '',
+ ["a\nc\ne", "a\nb\nc"], "a\nc\n", 0],
+# missing last NUL at the end of the last line (=end of file)
+['z4', '-z',
+ ["a\0c\0e", "a\0b\0c"], "a\0c\0", 0],
+# edge-case: the embedded newlines should treated as
+# part of the nul-terminated line
+['z5', '-z -a1 -a2',
+ ["a\n1\0c 3\0","b\n8\0c 9\0"], "a\n1\0b\n8\0c 3 9\0"],
+
 );
 
 # Convert the above old-style test vectors to the newer