Mercurial > hg > toybox
comparison toys/posix/paste.c @ 943:8cb7d65a40e8
here's a version of paste. It doesn't deal with wide characters yet and
likely behaves very badly when given too many files or delimiters.
author | Felix Janda <felix.janda@posteo.de> |
---|---|
date | Wed, 03 Jul 2013 02:29:24 -0500 |
parents | |
children | b4faf2ae39e8 |
comparison
equal
deleted
inserted
replaced
942:f8db1f6ec4ab | 943:8cb7d65a40e8 |
---|---|
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 * | |
7 USE_PASTE(NEWTOY(paste, "d:s", TOYFLAG_BIN)) | |
8 | |
9 config 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 | |
25 GLOBALS( | |
26 char *delim; | |
27 ) | |
28 | |
29 void 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 } |