diff options
Diffstat (limited to 'toys/posix/paste.c')
-rw-r--r-- | toys/posix/paste.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/toys/posix/paste.c b/toys/posix/paste.c new file mode 100644 index 00000000..92a52534 --- /dev/null +++ b/toys/posix/paste.c @@ -0,0 +1,100 @@ +/* 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; + char **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"; + p = TT.delim; + for (; *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("%s", *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("%s", *args); + } + for (; 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'); + } + } + } +} |