1 /* paste.c - Replace newlines
2 *
3 * Copyright 2012 Felix Janda <felix.janda@posteo.de>
4 *
5 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/paste.html
6 *
7 USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_BIN))
8
9 config PASTE
10 bool "paste"
11 default y
12 help
13 usage: paste [-s] [-d list] [file...]
14
15 Replace newlines in files.
16
17 -d list list of delimiters to separate lines
18 -s process files sequentially instead of in parallel
19
20 By default print corresponding lines separated by <tab>.
21 */
22 #define FOR_paste
23 #include "toys.h"
24
GLOBALS(char * delim;)25 GLOBALS(
26 char *delim;
27 )
28
29 void paste_main(void)
30 {
31 char *p, *buf = toybuf, **args = toys.optargs;
32 size_t ndelim = 0;
33 int i, j, c;
34
35 // Process delimiter list
36 // TODO: Handle multibyte characters
37 if (!(toys.optflags & FLAG_d)) TT.delim = "\t";
38 for (p = TT.delim; *p; p++, buf++, ndelim++) {
39 if (*p == '\\') {
40 p++;
41 if (-1 == (i = stridx("nt\\0", *p)))
42 error_exit("bad delimiter: \\%c", *p);
43 *buf = "\n\t\\\0"[i];
44 } else *buf = *p;
45 }
46 *buf = 0;
47
48 if (toys.optflags & FLAG_s) { // Sequential
49 FILE *f;
50
51 for (; *args; args++) {
52 if ((*args)[0] == '-' && !(*args)[1]) f = stdin;
53 else if (!(f = fopen(*args, "r"))) perror_exit("%s", *args);
54 for (i = 0, c = 0; c != EOF;) {
55 switch(c = getc(f)) {
56 case '\n':
57 putchar(toybuf[i++ % ndelim]);
58 case EOF:
59 break;
60 default:
61 putchar(c);
62 }
63 }
64 if (f != stdin) fclose(f);
65 putchar('\n');
66 }
67 } else { // Parallel
68 // Need to be careful not to print an extra line at the end
69 FILE **files;
70 int anyopen = 1;
71
72 files = (FILE**)(buf + 1);
73 for (; *args; args++, files++) {
74 if ((*args)[0] == '-' && !(*args)[1]) *files = stdin;
75 else if (!(*files = fopen(*args, "r"))) perror_exit("%s", *args);
76 }
77 while (anyopen) {
78 anyopen = 0;
79 for (i = 0; i < toys.optc; i++) {
80 FILE **f = (FILE**)(buf + 1) + i;
81
82 if (*f) for (;;) {
83 c = getc(*f);
84 if (c != EOF) {
85 if (!anyopen++) for (j = 0; j < i; j++) putchar(toybuf[j % ndelim]);
86 if (c != '\n') putchar(c);
87 else break;
88 }
89 else {
90 if (*f != stdin) fclose(*f);
91 *f = 0;
92 break;
93 }
94 }
95 if (anyopen) putchar((i + 1 == toys.optc) ? toybuf[i % ndelim] : '\n');
96 }
97 }
98 }
99 }
100