1 /* paste - merge lines of files
2 Copyright (C) 1997-2005, 2008 Free Software Foundation, Inc.
3 Copyright (C) 1984 David M. Ihnat
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 /* Written by David Ihnat. */
20 /* The list of valid escape sequences has been expanded over the Unix
21 version, to include \b, \f, \r, and \v.
23 POSIX changes, bug fixes, long-named options, and cleanup
24 by David MacKenzie <djm@gnu.ai.mit.edu>.
28 -s Paste one file at a time rather than
29 one line from each file.
30 --delimiters=delim-list
31 -d delim-list Consecutively use the characters in
32 DELIM-LIST instead of tab to separate
33 merged lines. When DELIM-LIST is exhausted,
34 start again at its beginning.
35 A FILE of `-' means standard input.
36 If no FILEs are given, standard input is used. */
42 #include <sys/types.h>
47 /* The official name of this program (e.g., no `g' prefix). */
48 #define PROGRAM_NAME "paste"
50 #define AUTHORS "David M. Ihnat", "David MacKenzie"
52 /* Indicates that no delimiter should be added in the current position. */
53 #define EMPTY_DELIM '\0'
55 /* Name this program was run with. */
58 /* If nonzero, we have read standard input at some point. */
59 static bool have_read_stdin;
61 /* If nonzero, merge subsequent lines of each file rather than
62 corresponding lines from each file in parallel. */
63 static bool serial_merge;
65 /* The delimeters between lines of input files (used cyclically). */
68 /* A pointer to the character after the end of `delims'. */
69 static char const *delim_end;
71 static struct option const longopts[] =
73 {"serial", no_argument, NULL, 's'},
74 {"delimiters", required_argument, NULL, 'd'},
75 {GETOPT_HELP_OPTION_DECL},
76 {GETOPT_VERSION_OPTION_DECL},
80 /* Set globals delims and delim_end. Copy STRPTR to DELIMS, converting
81 backslash representations of special characters in STRPTR to their actual
82 values. The set of possible backslash characters has been expanded beyond
83 that recognized by the Unix version.
84 Return 0 upon success.
85 If the string ends in an odd number of backslashes, ignore the
86 final backslash and return nonzero. */
89 collapse_escapes (char const *strptr)
91 char *strout = xstrdup (strptr);
92 bool backslash_at_end = false;
98 if (*strptr != '\\') /* Is it an escape character? */
99 *strout++ = *strptr++; /* No, just transfer it. */
105 *strout++ = EMPTY_DELIM;
137 backslash_at_end = true;
151 return backslash_at_end ? 1 : 0;
154 /* Report a write error and exit. */
156 static void write_error (void) ATTRIBUTE_NORETURN;
160 error (EXIT_FAILURE, errno, _("write error"));
164 /* Output a single byte, reporting any write errors. */
173 /* Perform column paste on the NFILES files named in FNAMPTR.
174 Return true if successful, false if one or more files could not be
178 paste_parallel (size_t nfiles, char **fnamptr)
181 /* If all files are just ready to be closed, or will be on this
182 round, the string of delimiters must be preserved.
183 delbuf[0] through delbuf[nfiles]
184 store the delimiters for closed files. */
185 char *delbuf = xmalloc (nfiles + 2);
187 /* Streams open to the files to process; NULL if the corresponding
189 FILE **fileptr = xnmalloc (nfiles + 1, sizeof *fileptr);
191 /* Number of files still open to process. */
194 /* True if any fopen got fd == STDIN_FILENO. */
195 bool opened_stdin = false;
197 /* Attempt to open all files. This could be expanded to an infinite
198 number of files, but at the (considerable) expense of remembering
199 each file and its current offset, then opening/reading/closing. */
201 for (files_open = 0; files_open < nfiles; ++files_open)
203 if (STREQ (fnamptr[files_open], "-"))
205 have_read_stdin = true;
206 fileptr[files_open] = stdin;
210 fileptr[files_open] = fopen (fnamptr[files_open], "r");
211 if (fileptr[files_open] == NULL)
212 error (EXIT_FAILURE, errno, "%s", fnamptr[files_open]);
213 else if (fileno (fileptr[files_open]) == STDIN_FILENO)
218 if (opened_stdin && have_read_stdin)
219 error (EXIT_FAILURE, 0, _("standard input is closed"));
221 /* Read a line from each file and output it to stdout separated by a
222 delimiter, until we go through the loop without successfully
223 reading from any of the files. */
227 /* Set up for the next line. */
228 bool somedone = false;
229 char const *delimptr = delims;
230 size_t delims_saved = 0; /* Number of delims saved in `delbuf'. */
233 for (i = 0; i < nfiles && files_open; i++)
235 int chr IF_LINT (= 0); /* Input character. */
236 int err IF_LINT (= 0); /* Input errno value. */
237 size_t line_length = 0; /* Number of chars in line. */
241 chr = getc (fileptr[i]);
243 if (chr != EOF && delims_saved)
245 if (fwrite (delbuf, 1, delims_saved, stdout) != delims_saved)
256 chr = getc (fileptr[i]);
261 if (line_length == 0)
263 /* EOF, read error, or closed file.
264 If an EOF or error, close the file. */
267 if (ferror (fileptr[i]))
269 error (0, err, "%s", fnamptr[i]);
272 if (fileptr[i] == stdin)
273 clearerr (fileptr[i]); /* Also clear EOF. */
274 else if (fclose (fileptr[i]) == EOF)
276 error (0, errno, "%s", fnamptr[i]);
286 /* End of this output line.
287 Is this the end of the whole thing? */
290 /* No. Some files were not closed for this line. */
293 if (fwrite (delbuf, 1, delims_saved, stdout)
300 continue; /* Next read of files, or exit. */
304 /* Closed file; add delimiter to `delbuf'. */
305 if (*delimptr != EMPTY_DELIM)
306 delbuf[delims_saved++] = *delimptr;
307 if (++delimptr == delim_end)
313 /* Some data read. */
316 /* Except for last file, replace last newline with delim. */
319 if (chr != '\n' && chr != EOF)
321 if (*delimptr != EMPTY_DELIM)
322 xputchar (*delimptr);
323 if (++delimptr == delim_end)
328 /* If the last line of the last file lacks a newline,
329 print one anyhow. POSIX requires this. */
330 char c = (chr == EOF ? '\n' : chr);
341 /* Perform serial paste on the NFILES files named in FNAMPTR.
342 Return true if no errors, false if one or more files could not be
346 paste_serial (size_t nfiles, char **fnamptr)
348 bool ok = true; /* false if open or read errors occur. */
349 int charnew, charold; /* Current and previous char read. */
350 char const *delimptr; /* Current delimiter char. */
351 FILE *fileptr; /* Open for reading current file. */
353 for (; nfiles; nfiles--, fnamptr++)
356 bool is_stdin = STREQ (*fnamptr, "-");
359 have_read_stdin = true;
364 fileptr = fopen (*fnamptr, "r");
367 error (0, errno, "%s", *fnamptr);
373 delimptr = delims; /* Set up for delimiter string. */
375 charold = getc (fileptr);
379 /* `charold' is set up. Hit it!
380 Keep reading characters, stashing them in `charnew';
381 output `charold', converting to the appropriate delimiter
382 character if needed. After the EOF, output `charold'
383 if it's a newline; otherwise, output it and then a newline. */
385 while ((charnew = getc (fileptr)) != EOF)
387 /* Process the old character. */
390 if (*delimptr != EMPTY_DELIM)
391 xputchar (*delimptr);
393 if (++delimptr == delim_end)
403 /* Hit EOF. Process that last character. */
410 if (ferror (fileptr))
412 error (0, saved_errno, "%s", *fnamptr);
416 clearerr (fileptr); /* Also clear EOF. */
417 else if (fclose (fileptr) == EOF)
419 error (0, errno, "%s", *fnamptr);
429 if (status != EXIT_SUCCESS)
430 fprintf (stderr, _("Try `%s --help' for more information.\n"),
435 Usage: %s [OPTION]... [FILE]...\n\
439 Write lines consisting of the sequentially corresponding lines from\n\
440 each FILE, separated by TABs, to standard output.\n\
441 With no FILE, or when FILE is -, read standard input.\n\
445 Mandatory arguments to long options are mandatory for short options too.\n\
448 -d, --delimiters=LIST reuse characters from LIST instead of TABs\n\
449 -s, --serial paste one file at a time instead of in parallel\n\
451 fputs (HELP_OPTION_DESCRIPTION, stdout);
452 fputs (VERSION_OPTION_DESCRIPTION, stdout);
453 /* FIXME: add a couple of examples. */
454 emit_bug_reporting_address ();
460 main (int argc, char **argv)
464 char const *delim_arg = "\t";
466 initialize_main (&argc, &argv);
467 program_name = argv[0];
468 setlocale (LC_ALL, "");
469 bindtextdomain (PACKAGE, LOCALEDIR);
470 textdomain (PACKAGE);
472 atexit (close_stdout);
474 have_read_stdin = false;
475 serial_merge = false;
477 while ((optc = getopt_long (argc, argv, "d:s", longopts, NULL)) != -1)
482 /* Delimiter character(s). */
483 delim_arg = (optarg[0] == '\0' ? "\\0" : optarg);
490 case_GETOPT_HELP_CHAR;
492 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
495 usage (EXIT_FAILURE);
502 if (collapse_escapes (delim_arg))
504 /* Don't use the default quoting style, because that would double the
505 number of displayed backslashes, making the diagnostic look bogus. */
506 set_quoting_style (NULL, escape_quoting_style);
507 error (EXIT_FAILURE, 0,
508 _("delimiter list ends with an unescaped backslash: %s"),
509 quotearg_colon (delim_arg));
513 ok = paste_parallel (argc - optind, &argv[optind]);
515 ok = paste_serial (argc - optind, &argv[optind]);
519 if (have_read_stdin && fclose (stdin) == EOF)
520 error (EXIT_FAILURE, errno, "-");
521 exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);