paste.c revision 8e9ec867e5753e63778d67c3cb1cce68792f7b24
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 * 7USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_BIN)) 8 9config 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 25GLOBALS( 26 char *delim; 27) 28 29void paste_main(void) 30{ 31 char *p, *buf = toybuf; 32 char **args = toys.optargs; 33 size_t ndelim = 0; 34 int i, j, c; 35 36 // Process delimiter list 37 // TODO: Handle multibyte characters 38 if (!(toys.optflags & FLAG_d)) TT.delim = "\t"; 39 p = TT.delim; 40 for (; *p; p++, buf++, ndelim++) { 41 if (*p == '\\') { 42 p++; 43 if (-1 == (i = stridx("nt\\0", *p))) 44 error_exit("bad delimiter: \\%c", *p); 45 *buf = "\n\t\\\0"[i]; 46 } 47 else *buf = *p; 48 } 49 *buf = 0; 50 51 if (toys.optflags & FLAG_s) { // Sequential 52 FILE *f; 53 for (; *args; args++) { 54 if ((*args)[0] == '-' && !(*args)[1]) f = stdin; 55 else if (!(f = fopen(*args, "r"))) perror_exit("%s", *args); 56 for (i = 0, c = 0; c != EOF;) { 57 switch(c = getc(f)) { 58 case '\n': 59 putchar(toybuf[i++ % ndelim]); 60 case EOF: 61 break; 62 default: 63 putchar(c); 64 } 65 } 66 if (f != stdin) fclose(f); 67 putchar('\n'); 68 } 69 } 70 else { // Parallel 71 // Need to be careful not to print an extra line at the end 72 FILE **files; 73 int anyopen = 1; 74 files = (FILE**)(buf + 1); 75 for (; *args; args++, files++) { 76 if ((*args)[0] == '-' && !(*args)[1]) *files = stdin; 77 else if (!(*files = fopen(*args, "r"))) perror_exit("%s", *args); 78 } 79 for (; anyopen;) { 80 anyopen = 0; 81 for (i = 0; i < toys.optc; i++) { 82 FILE **f = (FILE**)(buf + 1) + i; 83 if (*f) for (;;) { 84 c = getc(*f); 85 if (c != EOF) { 86 if (!anyopen++) for (j = 0; j < i; j++) putchar(toybuf[j % ndelim]); 87 if (c != '\n') putchar(c); 88 else break; 89 } 90 else { 91 if (*f != stdin) fclose(*f); 92 *f = 0; 93 break; 94 } 95 } 96 if (anyopen) putchar((i + 1 == toys.optc) ? toybuf[i % ndelim] : '\n'); 97 } 98 } 99 } 100} 101