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