paste.c (2590B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdlib.h> 3 #include <string.h> 4 5 #include "utf.h" 6 #include "util.h" 7 8 struct fdescr { 9 FILE *fp; 10 const char *name; 11 }; 12 13 static void 14 sequential(struct fdescr *dsc, int fdescrlen, Rune *delim, size_t delimlen) 15 { 16 Rune c, last; 17 size_t i, d; 18 19 for (i = 0; i < fdescrlen; i++) { 20 d = 0; 21 last = 0; 22 23 while (efgetrune(&c, dsc[i].fp, dsc[i].name)) { 24 if (last == '\n') { 25 if (delim[d] != '\0') 26 efputrune(&delim[d], stdout, "<stdout>"); 27 d = (d + 1) % delimlen; 28 } 29 30 if (c != '\n') 31 efputrune(&c, stdout, "<stdout>"); 32 last = c; 33 } 34 35 if (last == '\n') 36 efputrune(&last, stdout, "<stdout>"); 37 } 38 } 39 40 static void 41 parallel(struct fdescr *dsc, int fdescrlen, Rune *delim, size_t delimlen) 42 { 43 Rune c, d; 44 size_t i, m; 45 ssize_t last; 46 47 nextline: 48 last = -1; 49 50 for (i = 0; i < fdescrlen; i++) { 51 d = delim[i % delimlen]; 52 c = 0; 53 54 for (; efgetrune(&c, dsc[i].fp, dsc[i].name) ;) { 55 for (m = last + 1; m < i; m++) 56 efputrune(&(delim[m % delimlen]), stdout, "<stdout>"); 57 last = i; 58 if (c == '\n') { 59 if (i != fdescrlen - 1) 60 c = d; 61 efputrune(&c, stdout, "<stdout>"); 62 break; 63 } 64 efputrune(&c, stdout, "<stdout>"); 65 } 66 67 if (c == 0 && last != -1) { 68 if (i == fdescrlen - 1) 69 putchar('\n'); 70 else 71 efputrune(&d, stdout, "<stdout>"); 72 last++; 73 } 74 } 75 if (last != -1) 76 goto nextline; 77 } 78 79 static void 80 usage(void) 81 { 82 eprintf("usage: %s [-s] [-d list] file ...\n", argv0); 83 } 84 85 int 86 main(int argc, char *argv[]) 87 { 88 struct fdescr *dsc; 89 Rune *delim; 90 size_t delimlen, i; 91 int seq = 0, ret = 0; 92 char *adelim = "\t"; 93 94 ARGBEGIN { 95 case 's': 96 seq = 1; 97 break; 98 case 'd': 99 adelim = EARGF(usage()); 100 unescape(adelim); 101 break; 102 default: 103 usage(); 104 } ARGEND 105 106 if (!argc) 107 usage(); 108 109 /* populate delimiters */ 110 /* TODO: fix libutf to accept sizes */ 111 delim = ereallocarray(NULL, utflen(adelim) + 1, sizeof(*delim)); 112 if (!(delimlen = utftorunestr(adelim, delim))) 113 usage(); 114 115 /* populate file list */ 116 dsc = ereallocarray(NULL, argc, sizeof(*dsc)); 117 118 for (i = 0; i < argc; i++) { 119 if (!strcmp(argv[i], "-")) { 120 argv[i] = "<stdin>"; 121 dsc[i].fp = stdin; 122 } else if (!(dsc[i].fp = fopen(argv[i], "r"))) { 123 eprintf("fopen %s:", argv[i]); 124 } 125 dsc[i].name = argv[i]; 126 } 127 128 if (seq) { 129 sequential(dsc, argc, delim, delimlen); 130 } else { 131 parallel(dsc, argc, delim, delimlen); 132 } 133 134 for (i = 0; i < argc; i++) 135 if (dsc[i].fp != stdin && fshut(dsc[i].fp, argv[i])) 136 ret |= fshut(dsc[i].fp, argv[i]); 137 138 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"); 139 140 return ret; 141 }