paste.c revision 1.4 1 /* $NetBSD: paste.c,v 1.4 1997/10/19 12:36:29 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam S. Moskowitz of Menlo Consulting.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
42 The Regents of the University of California. All rights reserved.\n");
43 #endif /* not lint */
44
45 #ifndef lint
46 /*static char sccsid[] = "from: @(#)paste.c 8.1 (Berkeley) 6/6/93";*/
47 __RCSID("$NetBSD: paste.c,v 1.4 1997/10/19 12:36:29 lukem Exp $");
48 #endif /* not lint */
49
50 #include <sys/types.h>
51 #include <err.h>
52 #include <errno.h>
53 #include <limits.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57
58 int main __P((int, char **));
59 void parallel __P((char **));
60 void sequential __P((char **));
61 int tr __P((char *));
62 void usage __P((void));
63
64 char *delim;
65 int delimcnt;
66
67 int
68 main(argc, argv)
69 int argc;
70 char **argv;
71 {
72 int ch, seq;
73
74 seq = 0;
75 while ((ch = getopt(argc, argv, "d:s")) != -1)
76 switch(ch) {
77 case 'd':
78 delimcnt = tr(delim = optarg);
79 break;
80 case 's':
81 seq = 1;
82 break;
83 case '?':
84 default:
85 usage();
86 }
87 argc -= optind;
88 argv += optind;
89
90 if (!delim) {
91 delimcnt = 1;
92 delim = "\t";
93 }
94
95 if (seq)
96 sequential(argv);
97 else
98 parallel(argv);
99 exit(0);
100 }
101
102 typedef struct _list {
103 struct _list *next;
104 FILE *fp;
105 int cnt;
106 char *name;
107 } LIST;
108
109 void
110 parallel(argv)
111 char **argv;
112 {
113 LIST *lp;
114 int cnt;
115 char ch, *p;
116 LIST *head, *tmp;
117 int opencnt, output;
118 char buf[_POSIX2_LINE_MAX + 1];
119
120 tmp = NULL;
121 for (cnt = 0, head = NULL; (p = *argv) != NULL; ++argv, ++cnt) {
122 if (!(lp = (LIST *)malloc((u_int)sizeof(LIST))))
123 err(1, "malloc");
124 if (p[0] == '-' && !p[1])
125 lp->fp = stdin;
126 else if (!(lp->fp = fopen(p, "r")))
127 err(1, "%s", p);
128 lp->next = NULL;
129 lp->cnt = cnt;
130 lp->name = p;
131 if (!head)
132 head = tmp = lp;
133 else {
134 tmp->next = lp;
135 tmp = lp;
136 }
137 }
138
139 for (opencnt = cnt; opencnt;) {
140 for (output = 0, lp = head; lp; lp = lp->next) {
141 if (!lp->fp) {
142 if (output && lp->cnt &&
143 (ch = delim[(lp->cnt - 1) % delimcnt]))
144 putchar(ch);
145 continue;
146 }
147 if (!fgets(buf, sizeof(buf), lp->fp)) {
148 if (!--opencnt)
149 break;
150 lp->fp = NULL;
151 if (output && lp->cnt &&
152 (ch = delim[(lp->cnt - 1) % delimcnt]))
153 putchar(ch);
154 continue;
155 }
156 if (!(p = strchr(buf, '\n')))
157 err(1, "%s: input line too long.", lp->name);
158 *p = '\0';
159 /*
160 * make sure that we don't print any delimiters
161 * unless there's a non-empty file.
162 */
163 if (!output) {
164 output = 1;
165 for (cnt = 0; cnt < lp->cnt; ++cnt)
166 if ((ch = delim[cnt % delimcnt]) != 0)
167 putchar(ch);
168 } else if ((ch = delim[(lp->cnt - 1) % delimcnt]) != 0)
169 putchar(ch);
170 (void)printf("%s", buf);
171 }
172 if (output)
173 putchar('\n');
174 }
175 }
176
177 void
178 sequential(argv)
179 char **argv;
180 {
181 FILE *fp;
182 int cnt;
183 char ch, *p, *dp;
184 char buf[_POSIX2_LINE_MAX + 1];
185
186 for (; (p = *argv) != NULL; ++argv) {
187 if (p[0] == '-' && !p[1])
188 fp = stdin;
189 else if (!(fp = fopen(p, "r"))) {
190 warn("%s", p);
191 continue;
192 }
193 if (fgets(buf, sizeof(buf), fp)) {
194 for (cnt = 0, dp = delim;;) {
195 if (!(p = strchr(buf, '\n')))
196 err(1, "%s: input line too long.",
197 *argv);
198 *p = '\0';
199 (void)printf("%s", buf);
200 if (!fgets(buf, sizeof(buf), fp))
201 break;
202 if ((ch = *dp++) != 0)
203 putchar(ch);
204 if (++cnt == delimcnt) {
205 dp = delim;
206 cnt = 0;
207 }
208 }
209 putchar('\n');
210 }
211 if (fp != stdin)
212 (void)fclose(fp);
213 }
214 }
215
216 int
217 tr(arg)
218 char *arg;
219 {
220 int cnt;
221 char ch, *p;
222
223 for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
224 if (ch == '\\')
225 switch(ch = *p++) {
226 case 'n':
227 *arg = '\n';
228 break;
229 case 't':
230 *arg = '\t';
231 break;
232 case '0':
233 *arg = '\0';
234 break;
235 default:
236 *arg = ch;
237 break;
238 } else
239 *arg = ch;
240
241 if (!cnt)
242 errx(1, "no delimiters specified.");
243 return(cnt);
244 }
245
246 void
247 usage()
248 {
249 (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
250 exit(1);
251 }
252