|
|
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: #endif /* not lint */
28:
29: #ifndef lint
30: static char sccsid[] = "@(#)paste.c 5.6 (Berkeley) 6/24/90";
31: #endif /* not lint */
32:
33: #include <sys/types.h>
34: #include <errno.h>
35: #include <limits.h>
36: #include <stdio.h>
37: #include <string.h>
38:
39: char *delim;
40: int delimcnt;
41:
42: main(argc, argv)
43: int argc;
44: char **argv;
45: {
46: extern char *optarg;
47: extern int optind;
48: int ch, seq;
49:
50: seq = 0;
51: while ((ch = getopt(argc, argv, "d:s")) != EOF)
52: switch(ch) {
53: case 'd':
54: delimcnt = tr(delim = optarg);
55: break;
56: case 's':
57: seq = 1;
58: break;
59: case '?':
60: default:
61: usage();
62: }
63: argc -= optind;
64: argv += optind;
65:
66: if (!delim) {
67: delimcnt = 1;
68: delim = "\t";
69: }
70:
71: if (seq)
72: sequential(argv);
73: else
74: parallel(argv);
75: exit(0);
76: }
77:
78: typedef struct _list {
79: struct _list *next;
80: FILE *fp;
81: int cnt;
82: char *name;
83: } LIST;
84:
85: parallel(argv)
86: char **argv;
87: {
88: register LIST *lp;
89: register int cnt;
90: register char ch, *p;
91: LIST *head, *tmp;
92: int opencnt, output;
93: char buf[_BSD_LINE_MAX + 1], *malloc();
94:
95: for (cnt = 0, head = NULL; p = *argv; ++argv, ++cnt) {
96: if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
97: (void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
98: exit(1);
99: }
100: if (p[0] == '-' && !p[1])
101: lp->fp = stdin;
102: else if (!(lp->fp = fopen(p, "r"))) {
103: (void)fprintf(stderr, "paste: %s: %s.\n", p,
104: strerror(errno));
105: exit(1);
106: }
107: lp->next = NULL;
108: lp->cnt = cnt;
109: lp->name = p;
110: if (!head)
111: head = tmp = lp;
112: else {
113: tmp->next = lp;
114: tmp = lp;
115: }
116: }
117:
118: for (opencnt = cnt; opencnt;) {
119: for (output = 0, lp = head; lp; lp = lp->next) {
120: if (!lp->fp) {
121: if (output && lp->cnt &&
122: (ch = delim[(lp->cnt - 1) % delimcnt]))
123: putchar(ch);
124: continue;
125: }
126: if (!fgets(buf, sizeof(buf), lp->fp)) {
127: if (!--opencnt)
128: break;
129: lp->fp = NULL;
130: if (output && lp->cnt &&
131: (ch = delim[(lp->cnt - 1) % delimcnt]))
132: putchar(ch);
133: continue;
134: }
135: if (!(p = index(buf, '\n'))) {
136: (void)fprintf(stderr,
137: "paste: %s: input line too long.\n",
138: lp->name);
139: exit(1);
140: }
141: *p = '\0';
142: /*
143: * make sure that we don't print any delimiters
144: * unless there's a non-empty file.
145: */
146: if (!output) {
147: output = 1;
148: for (cnt = 0; cnt < lp->cnt; ++cnt)
149: if (ch = delim[cnt % delimcnt])
150: putchar(ch);
151: } else if (ch = delim[(lp->cnt - 1) % delimcnt])
152: putchar(ch);
153: (void)printf("%s", buf);
154: }
155: if (output)
156: putchar('\n');
157: }
158: }
159:
160: sequential(argv)
161: char **argv;
162: {
163: register FILE *fp;
164: register int cnt;
165: register char ch, *p, *dp;
166: char buf[_BSD_LINE_MAX + 1];
167:
168: for (; p = *argv; ++argv) {
169: if (p[0] == '-' && !p[1])
170: fp = stdin;
171: else if (!(fp = fopen(p, "r"))) {
172: (void)fprintf(stderr, "paste: %s: %s.\n", p,
173: strerror(errno));
174: continue;
175: }
176: if (fgets(buf, sizeof(buf), fp)) {
177: for (cnt = 0, dp = delim;;) {
178: if (!(p = index(buf, '\n'))) {
179: (void)fprintf(stderr,
180: "paste: %s: input line too long.\n",
181: *argv);
182: exit(1);
183: }
184: *p = '\0';
185: (void)printf("%s", buf);
186: if (!fgets(buf, sizeof(buf), fp))
187: break;
188: if (ch = *dp++)
189: putchar(ch);
190: if (++cnt == delimcnt) {
191: dp = delim;
192: cnt = 0;
193: }
194: }
195: putchar('\n');
196: }
197: if (fp != stdin)
198: (void)fclose(fp);
199: }
200: }
201:
202: tr(arg)
203: char *arg;
204: {
205: register int cnt;
206: register char ch, *p;
207:
208: for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
209: if (ch == '\\')
210: switch(ch = *p++) {
211: case 'n':
212: *arg = '\n';
213: break;
214: case 't':
215: *arg = '\t';
216: break;
217: case '0':
218: *arg = '\0';
219: break;
220: default:
221: *arg = ch;
222: break;
223: } else
224: *arg = ch;
225:
226: if (!cnt) {
227: (void)fprintf(stderr, "paste: no delimiters specified.\n");
228: exit(1);
229: }
230: return(cnt);
231: }
232:
233: usage()
234: {
235: (void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
236: exit(1);
237: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.