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 }