|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Adam S. Moskowitz of Menlo Consulting.
7: *
8: * Redistribution and use in source and binary forms are permitted provided
9: * that: (1) source distributions retain this entire copyright notice and
10: * comment, and (2) distributions including binaries display the following
11: * acknowledgement: ``This product includes software developed by the
12: * University of California, Berkeley and its contributors'' in the
13: * documentation or other materials provided with the distribution and in
14: * all advertising materials mentioning features or use of this software.
15: * Neither the name of the University nor the names of its contributors may
16: * be used to endorse or promote products derived from this software without
17: * specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #ifndef lint
24: char copyright[] =
25: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
26: All rights reserved.\n";
27: static char sccsid[] = "@(#)paste.c 5.6 (Berkeley) 6/24/90";
28: #endif /* not lint */
29:
30: #include <sys/types.h>
31: #include <errno.h>
32: #include <limits.h>
33: #include <stdio.h>
34: #include <string.h>
35:
36: #if COHERENT
37: #define _BSD_LINE_MAX BUFSIZ /* compatibility */
38: typedef unsigned int u_int;
39: char *index();
40: #endif
41:
42: char *delim;
43: int delimcnt;
44:
45: main(argc, argv)
46: int argc;
47: char **argv;
48: {
49: extern char *optarg;
50: extern int optind;
51: int ch, seq;
52:
53: seq = 0;
54: while ((ch = getopt(argc, argv, "d:s")) != EOF)
55: switch(ch) {
56: case 'd':
57: delimcnt = tr(delim = optarg);
58: break;
59: case 's':
60: seq = 1;
61: break;
62: case '?':
63: default:
64: usage();
65: }
66: argc -= optind;
67: argv += optind;
68:
69: if (!delim) {
70: delimcnt = 1;
71: delim = "\t";
72: }
73:
74: if (seq)
75: sequential(argv);
76: else
77: parallel(argv);
78: exit(0);
79: }
80:
81: typedef struct _list {
82: struct _list *next;
83: FILE *fp;
84: int cnt;
85: char *name;
86: } LIST;
87:
88: parallel(argv)
89: char **argv;
90: {
91: register LIST *lp;
92: register int cnt;
93: register char ch, *p;
94: LIST *head, *tmp;
95: int opencnt, output;
96: char buf[_BSD_LINE_MAX + 1], *malloc();
97:
98: for (cnt = 0, head = NULL; p = *argv; ++argv, ++cnt) {
99: if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
100: (void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
101: exit(1);
102: }
103: if (p[0] == '-' && !p[1])
104: lp->fp = stdin;
105: else if (!(lp->fp = fopen(p, "r"))) {
106: (void)fprintf(stderr, "paste: %s: %s.\n", p,
107: strerror(errno));
108: exit(1);
109: }
110: lp->next = NULL;
111: lp->cnt = cnt;
112: lp->name = p;
113: if (!head)
114: head = tmp = lp;
115: else {
116: tmp->next = lp;
117: tmp = lp;
118: }
119: }
120:
121: for (opencnt = cnt; opencnt;) {
122: for (output = 0, lp = head; lp; lp = lp->next) {
123: if (!lp->fp) {
124: if (output && lp->cnt &&
125: (ch = delim[(lp->cnt - 1) % delimcnt]))
126: putchar(ch);
127: continue;
128: }
129: if (!fgets(buf, sizeof(buf), lp->fp)) {
130: if (!--opencnt)
131: break;
132: lp->fp = NULL;
133: if (output && lp->cnt &&
134: (ch = delim[(lp->cnt - 1) % delimcnt]))
135: putchar(ch);
136: continue;
137: }
138: if (!(p = index(buf, '\n'))) {
139: (void)fprintf(stderr,
140: "paste: %s: input line too long.\n",
141: lp->name);
142: exit(1);
143: }
144: *p = '\0';
145: /*
146: * make sure that we don't print any delimiters
147: * unless there's a non-empty file.
148: */
149: if (!output) {
150: output = 1;
151: for (cnt = 0; cnt < lp->cnt; ++cnt)
152: if (ch = delim[cnt % delimcnt])
153: putchar(ch);
154: } else if (ch = delim[(lp->cnt - 1) % delimcnt])
155: putchar(ch);
156: (void)printf("%s", buf);
157: }
158: if (output)
159: putchar('\n');
160: }
161: }
162:
163: sequential(argv)
164: char **argv;
165: {
166: register FILE *fp;
167: register int cnt;
168: register char ch, *p, *dp;
169: char buf[_BSD_LINE_MAX + 1];
170:
171: for (; p = *argv; ++argv) {
172: if (p[0] == '-' && !p[1])
173: fp = stdin;
174: else if (!(fp = fopen(p, "r"))) {
175: (void)fprintf(stderr, "paste: %s: %s.\n", p,
176: strerror(errno));
177: continue;
178: }
179: if (fgets(buf, sizeof(buf), fp)) {
180: for (cnt = 0, dp = delim;;) {
181: if (!(p = index(buf, '\n'))) {
182: (void)fprintf(stderr,
183: "paste: %s: input line too long.\n",
184: *argv);
185: exit(1);
186: }
187: *p = '\0';
188: (void)printf("%s", buf);
189: if (!fgets(buf, sizeof(buf), fp))
190: break;
191: if (ch = *dp++)
192: putchar(ch);
193: if (++cnt == delimcnt) {
194: dp = delim;
195: cnt = 0;
196: }
197: }
198: putchar('\n');
199: }
200: if (fp != stdin)
201: (void)fclose(fp);
202: }
203: }
204:
205: tr(arg)
206: char *arg;
207: {
208: register int cnt;
209: register char ch, *p;
210:
211: for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
212: if (ch == '\\')
213: switch(ch = *p++) {
214: case 'n':
215: *arg = '\n';
216: break;
217: case 't':
218: *arg = '\t';
219: break;
220: case '0':
221: *arg = '\0';
222: break;
223: default:
224: *arg = ch;
225: break;
226: } else
227: *arg = ch;
228:
229: if (!cnt) {
230: (void)fprintf(stderr, "paste: no delimiters specified.\n");
231: exit(1);
232: }
233: return(cnt);
234: }
235:
236: usage()
237: {
238: (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
239: exit(1);
240: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.