99 lines
2.4 KiB
C
99 lines
2.4 KiB
C
/* 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');
|
|
}
|
|
}
|
|
}
|
|
}
|