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