/* paste.c - Replace newlines * * Copyright 2012 Felix Janda * * 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 . */ #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'); } } } }