xref: /original-bsd/usr.bin/lam/lam.c (revision e2944021)
1 /* Copyright (c) 1983 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)lam.c	4.4	(Berkeley)	04/05/86";
5 #endif not lint
6 
7 /*
8  *	lam - laminate files
9  *	Author:  John Kunze, Office of Comp. Affairs, UCB
10  */
11 
12 #include <stdio.h>
13 
14 #define	MAXOFILES	20
15 #define	BIGBUFSIZ	5 * BUFSIZ
16 
17 struct	openfile {		/* open file structure */
18 	FILE	*fp;		/* file pointer */
19 	short	eof;		/* eof flag */
20 	short	pad;		/* pad flag for missing columns */
21 	char	eol;		/* end of line character */
22 	char	*sepstring;	/* string to print before each line */
23 	char	*format;	/* printf(3) style string spec. */
24 }	input[MAXOFILES];
25 
26 int	morefiles;		/* set by getargs(), changed by gatherline() */
27 int	nofinalnl;		/* normally append \n to each output line */
28 char	buf[BUFSIZ];
29 char	line[BIGBUFSIZ];
30 char	*linep;
31 
32 main(argc, argv)
33 int	argc;
34 char	**argv;
35 {
36 	register struct	openfile	*ip;
37 	char	*gatherline();
38 
39 	setbuf(stdout, buf);
40 	getargs(argv);
41 	if (!morefiles)
42 		error("lam - laminate files", "");
43 	for (;;) {
44 		linep = line;
45 		for (ip = input; ip->fp != NULL; ip++)
46 			linep = gatherline(ip);
47 		if (!morefiles)
48 			exit(0);
49 		fputs(line, stdout);
50 		fputs(ip->sepstring, stdout);
51 		if (!nofinalnl)
52 			putchar('\n');
53 	}
54 }
55 
56 getargs(av)
57 char	**av;
58 {
59 	register struct	openfile	*ip = input;
60 	register char	*p;
61 	register char	*c;
62 	static	char	fmtbuf[BUFSIZ];
63 	char	*fmtp = fmtbuf;
64 	int	P, S, F, T;
65 
66 	P = S = F = T = 0;		/* capitalized options */
67 	while (p = *++av) {
68 		if (*p != '-' || !p[1]) {
69 			morefiles++;
70 			if (*p == '-')
71 				ip->fp = stdin;
72 			else if ((ip->fp = fopen(p, "r")) == NULL) {
73 				perror(p);
74 				exit(1);
75 			}
76 			ip->pad = P;
77 			if (!ip->sepstring)
78 				ip->sepstring = (S ? (ip-1)->sepstring : "");
79 			if (!ip->format)
80 				ip->format = (F ? (ip-1)->format : "%s");
81 			if (!ip->eol)
82 				ip->eol = (T ? (ip-1)->eol : '\n');
83 			ip++;
84 			continue;
85 		}
86 		switch (*(c = ++p) | 040) {
87 		case 's':
88 			if (*++p || (p = *++av))
89 				ip->sepstring = p;
90 			else
91 				error("Need string after -%s", c);
92 			S = (*c == 'S' ? 1 : 0);
93 			break;
94 		case 't':
95 			if (*++p || (p = *++av))
96 				ip->eol = *p;
97 			else
98 				error("Need character after -%s", c);
99 			T = (*c == 'T' ? 1 : 0);
100 			nofinalnl = 1;
101 			break;
102 		case 'p':
103 			ip->pad = 1;
104 			P = (*c == 'P' ? 1 : 0);
105 		case 'f':
106 			F = (*c == 'F' ? 1 : 0);
107 			if (*++p || (p = *++av)) {
108 				fmtp += strlen(fmtp);
109 				if (fmtp > fmtbuf + BUFSIZ)
110 					error("No more format space", "");
111 				sprintf(fmtp, "%%%ss", p);
112 				ip->format = fmtp;
113 			}
114 			else
115 				error("Need string after -%s", c);
116 			break;
117 		default:
118 			error("What do you mean by -%s?", c);
119 			break;
120 		}
121 	}
122 	ip->fp = NULL;
123 	if (!ip->sepstring)
124 		ip->sepstring = "";
125 }
126 
127 char	*
128 gatherline(ip)
129 struct	openfile	*ip;
130 {
131 	char	s[BUFSIZ];
132 	register int	c;
133 	register char	*p;
134 	register char	*lp = linep;
135 	char	*end = s + BUFSIZ;
136 
137 	if (ip->eof) {
138 		p = ip->sepstring;
139 		while (*p)
140 			*lp++ = *p++;
141 		if (ip->pad) {
142 			sprintf(lp, ip->format, "");
143 			lp += strlen(lp);
144 		}
145 		return(lp);
146 	}
147 	for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++)
148 		if ((*p = c) == ip->eol)
149 			break;
150 	*p = '\0';
151 	p = ip->sepstring;
152 	while (*p)
153 		*lp++ = *p++;
154 	sprintf(lp, ip->format, s);
155 	lp += strlen(lp);
156 	if (c == EOF) {
157 		ip->eof = 1;
158 		if (ip->fp == stdin)
159 			fclose(stdin);
160 		morefiles--;
161 	}
162 	return(lp);
163 }
164 
165 error(msg, s)
166 char	*msg;
167 char	*s;
168 {
169 	char	buf[BUFSIZ];
170 
171 	setbuf(stderr, buf);
172 	fprintf(stderr, "lam: ");
173 	fprintf(stderr, msg, s);
174 	fprintf(stderr, "\nUsage:  lam [ -[fp] min.max ] [ -s sepstring ] [ -t c ] file ...\n");
175 	if (strncmp("lam - ", msg, 6) == 0)
176 		fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s",
177 			"-f min.max	field widths for file fragments\n",
178 			"-p min.max	like -f, but pad missing fragments\n",
179 			"-s sepstring	fragment separator\n",
180 			"-t c		input line terminator is c, no \\n after output lines\n",
181 			"Capitalized options affect more than one file.\n");
182 	exit(1);
183 }
184