xref: /csrg-svn/usr.bin/paste/paste.c (revision 62161)
139826Sbostic /*
2*62161Sbostic  * Copyright (c) 1989, 1993
3*62161Sbostic  *	The Regents of the University of California.  All rights reserved.
439826Sbostic  *
539826Sbostic  * This code is derived from software contributed to Berkeley by
639826Sbostic  * Adam S. Moskowitz of Menlo Consulting.
739826Sbostic  *
842757Sbostic  * %sccs.include.redist.c%
939826Sbostic  */
1039826Sbostic 
1139826Sbostic #ifndef lint
12*62161Sbostic static char copyright[] =
13*62161Sbostic "@(#) Copyright (c) 1989, 1993\n\
14*62161Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1539826Sbostic #endif /* not lint */
1639826Sbostic 
1739826Sbostic #ifndef lint
18*62161Sbostic static char sccsid[] = "@(#)paste.c	8.1 (Berkeley) 06/06/93";
1939826Sbostic #endif /* not lint */
2039826Sbostic 
2139826Sbostic #include <sys/types.h>
2239826Sbostic #include <errno.h>
2339826Sbostic #include <limits.h>
2439826Sbostic #include <stdio.h>
2542756Sbostic #include <string.h>
2639826Sbostic 
2739826Sbostic char *delim;
2839826Sbostic int delimcnt;
2939826Sbostic 
main(argc,argv)3042756Sbostic main(argc, argv)
3139826Sbostic 	int argc;
3239826Sbostic 	char **argv;
3339826Sbostic {
3439826Sbostic 	extern char *optarg;
3539826Sbostic 	extern int optind;
3639826Sbostic 	int ch, seq;
3739826Sbostic 
3839826Sbostic 	seq = 0;
3939826Sbostic 	while ((ch = getopt(argc, argv, "d:s")) != EOF)
4039826Sbostic 		switch(ch) {
4139826Sbostic 		case 'd':
4239826Sbostic 			delimcnt = tr(delim = optarg);
4339826Sbostic 			break;
4439826Sbostic 		case 's':
4539826Sbostic 			seq = 1;
4639826Sbostic 			break;
4739826Sbostic 		case '?':
4839826Sbostic 		default:
4939826Sbostic 			usage();
5039826Sbostic 		}
5139826Sbostic 	argc -= optind;
5239826Sbostic 	argv += optind;
5339826Sbostic 
5439826Sbostic 	if (!delim) {
5539826Sbostic 		delimcnt = 1;
5639826Sbostic 		delim = "\t";
5739826Sbostic 	}
5839826Sbostic 
5939826Sbostic 	if (seq)
6039826Sbostic 		sequential(argv);
6139826Sbostic 	else
6239826Sbostic 		parallel(argv);
6339826Sbostic 	exit(0);
6439826Sbostic }
6539826Sbostic 
6639826Sbostic typedef struct _list {
6739826Sbostic 	struct _list *next;
6839826Sbostic 	FILE *fp;
6939826Sbostic 	int cnt;
7039826Sbostic 	char *name;
7139826Sbostic } LIST;
7239826Sbostic 
parallel(argv)7339826Sbostic parallel(argv)
7439826Sbostic 	char **argv;
7539826Sbostic {
7639826Sbostic 	register LIST *lp;
7739826Sbostic 	register int cnt;
7839826Sbostic 	register char ch, *p;
7939826Sbostic 	LIST *head, *tmp;
8039826Sbostic 	int opencnt, output;
8145442Sbostic 	char buf[_POSIX2_LINE_MAX + 1], *malloc();
8239826Sbostic 
8339826Sbostic 	for (cnt = 0, head = NULL; p = *argv; ++argv, ++cnt) {
8439826Sbostic 		if (!(lp = (LIST *)malloc((u_int)sizeof(LIST)))) {
8539826Sbostic 			(void)fprintf(stderr, "paste: %s.\n", strerror(ENOMEM));
8639826Sbostic 			exit(1);
8739826Sbostic 		}
8839826Sbostic 		if (p[0] == '-' && !p[1])
8939826Sbostic 			lp->fp = stdin;
9039826Sbostic 		else if (!(lp->fp = fopen(p, "r"))) {
9139826Sbostic 			(void)fprintf(stderr, "paste: %s: %s.\n", p,
9239826Sbostic 			    strerror(errno));
9339826Sbostic 			exit(1);
9439826Sbostic 		}
9539826Sbostic 		lp->next = NULL;
9639826Sbostic 		lp->cnt = cnt;
9739826Sbostic 		lp->name = p;
9839826Sbostic 		if (!head)
9939826Sbostic 			head = tmp = lp;
10039826Sbostic 		else {
10139826Sbostic 			tmp->next = lp;
10239826Sbostic 			tmp = lp;
10339826Sbostic 		}
10439826Sbostic 	}
10539826Sbostic 
10639826Sbostic 	for (opencnt = cnt; opencnt;) {
10740308Sbostic 		for (output = 0, lp = head; lp; lp = lp->next) {
10839826Sbostic 			if (!lp->fp) {
10940308Sbostic 				if (output && lp->cnt &&
11040308Sbostic 				    (ch = delim[(lp->cnt - 1) % delimcnt]))
11140308Sbostic 					putchar(ch);
11239826Sbostic 				continue;
11339826Sbostic 			}
11439826Sbostic 			if (!fgets(buf, sizeof(buf), lp->fp)) {
11539826Sbostic 				if (!--opencnt)
11639826Sbostic 					break;
11739826Sbostic 				lp->fp = NULL;
11840308Sbostic 				if (output && lp->cnt &&
11940308Sbostic 				    (ch = delim[(lp->cnt - 1) % delimcnt]))
12040308Sbostic 					putchar(ch);
12139826Sbostic 				continue;
12239826Sbostic 			}
12339826Sbostic 			if (!(p = index(buf, '\n'))) {
12439826Sbostic 				(void)fprintf(stderr,
12539826Sbostic 				    "paste: %s: input line too long.\n",
12639826Sbostic 				    lp->name);
12739826Sbostic 				exit(1);
12839826Sbostic 			}
12939826Sbostic 			*p = '\0';
13040308Sbostic 			/*
13140308Sbostic 			 * make sure that we don't print any delimiters
13240308Sbostic 			 * unless there's a non-empty file.
13340308Sbostic 			 */
13440308Sbostic 			if (!output) {
13540308Sbostic 				output = 1;
13640308Sbostic 				for (cnt = 0; cnt < lp->cnt; ++cnt)
13740308Sbostic 					if (ch = delim[cnt % delimcnt])
13840308Sbostic 						putchar(ch);
13940308Sbostic 			} else if (ch = delim[(lp->cnt - 1) % delimcnt])
14040308Sbostic 				putchar(ch);
14139826Sbostic 			(void)printf("%s", buf);
14239826Sbostic 		}
14339826Sbostic 		if (output)
14439826Sbostic 			putchar('\n');
14539826Sbostic 	}
14639826Sbostic }
14739826Sbostic 
sequential(argv)14839826Sbostic sequential(argv)
14939826Sbostic 	char **argv;
15039826Sbostic {
15139826Sbostic 	register FILE *fp;
15239826Sbostic 	register int cnt;
15339826Sbostic 	register char ch, *p, *dp;
15445442Sbostic 	char buf[_POSIX2_LINE_MAX + 1];
15539826Sbostic 
15639826Sbostic 	for (; p = *argv; ++argv) {
15739826Sbostic 		if (p[0] == '-' && !p[1])
15839826Sbostic 			fp = stdin;
15940306Sbostic 		else if (!(fp = fopen(p, "r"))) {
16039826Sbostic 			(void)fprintf(stderr, "paste: %s: %s.\n", p,
16139826Sbostic 			    strerror(errno));
16239826Sbostic 			continue;
16339826Sbostic 		}
16439826Sbostic 		if (fgets(buf, sizeof(buf), fp)) {
16539826Sbostic 			for (cnt = 0, dp = delim;;) {
16639826Sbostic 				if (!(p = index(buf, '\n'))) {
16739826Sbostic 					(void)fprintf(stderr,
16839826Sbostic 					    "paste: %s: input line too long.\n",
16939826Sbostic 					    *argv);
17039826Sbostic 					exit(1);
17139826Sbostic 				}
17239826Sbostic 				*p = '\0';
17339826Sbostic 				(void)printf("%s", buf);
17439826Sbostic 				if (!fgets(buf, sizeof(buf), fp))
17539826Sbostic 					break;
17639826Sbostic 				if (ch = *dp++)
17739826Sbostic 					putchar(ch);
17839826Sbostic 				if (++cnt == delimcnt) {
17939826Sbostic 					dp = delim;
18039826Sbostic 					cnt = 0;
18139826Sbostic 				}
18239826Sbostic 			}
18339826Sbostic 			putchar('\n');
18439826Sbostic 		}
18539826Sbostic 		if (fp != stdin)
18639826Sbostic 			(void)fclose(fp);
18739826Sbostic 	}
18839826Sbostic }
18939826Sbostic 
tr(arg)19039826Sbostic tr(arg)
19139826Sbostic 	char *arg;
19239826Sbostic {
19339826Sbostic 	register int cnt;
19439826Sbostic 	register char ch, *p;
19539826Sbostic 
19639826Sbostic 	for (p = arg, cnt = 0; (ch = *p++); ++arg, ++cnt)
19739826Sbostic 		if (ch == '\\')
19839826Sbostic 			switch(ch = *p++) {
19939826Sbostic 			case 'n':
20039826Sbostic 				*arg = '\n';
20139826Sbostic 				break;
20239826Sbostic 			case 't':
20339826Sbostic 				*arg = '\t';
20439826Sbostic 				break;
20539826Sbostic 			case '0':
20639826Sbostic 				*arg = '\0';
20739826Sbostic 				break;
20839826Sbostic 			default:
20939826Sbostic 				*arg = ch;
21039826Sbostic 				break;
21139826Sbostic 		} else
21239826Sbostic 			*arg = ch;
21339826Sbostic 
21439826Sbostic 	if (!cnt) {
21539826Sbostic 		(void)fprintf(stderr, "paste: no delimiters specified.\n");
21639826Sbostic 		exit(1);
21739826Sbostic 	}
21839826Sbostic 	return(cnt);
21939826Sbostic }
22039826Sbostic 
usage()22139826Sbostic usage()
22239826Sbostic {
22339826Sbostic 	(void)fprintf(stderr, "paste: [-s] [-d delimiters] file ...\n");
22439826Sbostic 	exit(1);
22539826Sbostic }
226