Fix markup.
[netbsd-mini2440.git] / usr.bin / paste / paste.c
blobd177b6dc50ad7642f4eb1b187c3eab14229cdd60
1 /* $NetBSD: paste.c,v 1.14 2008/07/21 14:19:24 lukem Exp $ */
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Adam S. Moskowitz of Menlo Consulting.
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 #ifndef lint
37 __COPYRIGHT("@(#) Copyright (c) 1989, 1993\
38 The Regents of the University of California. All rights reserved.");
39 #endif /* not lint */
41 #ifndef lint
42 /*static char sccsid[] = "from: @(#)paste.c 8.1 (Berkeley) 6/6/93";*/
43 __RCSID("$NetBSD: paste.c,v 1.14 2008/07/21 14:19:24 lukem Exp $");
44 #endif /* not lint */
46 #include <sys/types.h>
47 #include <err.h>
48 #include <errno.h>
49 #include <limits.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
55 void parallel(int, char **);
56 void sequential(char **);
57 int tr(char *);
58 void usage(void);
60 char dflt_delim[] = "\t";
61 char *delim = dflt_delim;
62 int delimcnt = 1;
64 int
65 main(int argc, char **argv)
67 int ch, seq;
69 seq = 0;
70 while ((ch = getopt(argc, argv, "d:s")) != -1) {
71 switch (ch) {
72 case 'd':
73 delim = strdup(optarg);
74 delimcnt = tr(delim);
75 break;
76 case 's':
77 seq = 1;
78 break;
79 case '?':
80 default:
81 usage();
84 argc -= optind;
85 argv += optind;
87 if (seq)
88 sequential(argv);
89 else
90 parallel(argc, argv);
91 exit(0);
94 void
95 parallel(int argc, char **argv)
97 char ch, *dp, *line;
98 FILE **fpp, *fp;
99 size_t line_len;
100 int cnt, output;
102 fpp = calloc(argc, sizeof *fpp);
103 if (fpp == NULL)
104 err(1, "calloc");
106 for (cnt = 0; cnt < argc; cnt++) {
107 if (strcmp(argv[cnt], "-") == 0)
108 fpp[cnt] = stdin;
109 else if (!(fpp[cnt] = fopen(argv[cnt], "r")))
110 err(1, "%s", argv[cnt]);
113 for (;;) {
114 /* Start with the NUL at the end of 'delim' ... */
115 dp = delim + delimcnt;
116 output = 0;
117 for (cnt = 0; cnt < argc; cnt++) {
118 fp = fpp[cnt];
119 if (fp == NULL)
120 continue;
121 line = fgetln(fp, &line_len);
122 if (line == NULL) {
123 /* Assume EOF */
124 if (fp != stdin)
125 fclose(fp);
126 fpp[cnt] = NULL;
127 continue;
129 /* Output enough separators to catch up */
130 do {
131 ch = *dp++;
132 if (ch)
133 putchar(ch);
134 if (dp >= delim + delimcnt)
135 dp = delim;
136 } while (++output <= cnt);
137 /* Remove any trailing newline - check for last line */
138 if (line[line_len - 1] == '\n')
139 line_len--;
140 printf("%.*s", (int)line_len, line);
143 if (!output)
144 break;
146 /* Add separators to end of line */
147 while (++output <= cnt) {
148 ch = *dp++;
149 if (ch)
150 putchar(ch);
151 if (dp >= delim + delimcnt)
152 dp = delim;
154 putchar('\n');
157 free(fpp);
160 void
161 sequential(char **argv)
163 FILE *fp;
164 int cnt;
165 char ch, *p, *dp;
166 char buf[_POSIX2_LINE_MAX + 1];
168 for (; (p = *argv) != NULL; ++argv) {
169 if (p[0] == '-' && !p[1])
170 fp = stdin;
171 else if (!(fp = fopen(p, "r"))) {
172 warn("%s", p);
173 continue;
175 if (fgets(buf, sizeof(buf), fp)) {
176 for (cnt = 0, dp = delim;;) {
177 if (!(p = strchr(buf, '\n')))
178 err(1, "%s: input line too long.",
179 *argv);
180 *p = '\0';
181 (void)printf("%s", buf);
182 if (!fgets(buf, sizeof(buf), fp))
183 break;
184 if ((ch = *dp++) != 0)
185 putchar(ch);
186 if (++cnt == delimcnt) {
187 dp = delim;
188 cnt = 0;
191 putchar('\n');
193 if (fp != stdin)
194 (void)fclose(fp);
199 tr(char *arg)
201 int cnt;
202 char ch, *p;
204 for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
205 if (ch == '\\')
206 switch(ch = *p++) {
207 case 'n':
208 *arg = '\n';
209 break;
210 case 't':
211 *arg = '\t';
212 break;
213 case '0':
214 *arg = '\0';
215 break;
216 default:
217 *arg = ch;
218 break;
219 } else
220 *arg = ch;
222 if (!cnt)
223 errx(1, "no delimiters specified.");
224 *arg = '\0';
225 return(cnt);
228 void
229 usage()
231 (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
232 exit(1);