xref: /original-bsd/usr.bin/lam/lam.c (revision bff54947)
1 /* Copyright (c) 1983 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)lam.c	4.5	(Berkeley)	05/19/88";
5 #endif not lint
6 
7 /*
8  *	lam - laminate files
9  *	Author:  John Kunze, 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 = ((P || 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) + 1;
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 pad(ip)
129 struct	openfile	*ip;
130 {
131 	register char	*p = ip->sepstring;
132 	register char	*lp = linep;
133 
134 	while (*p)
135 		*lp++ = *p++;
136 	if (ip->pad) {
137 		sprintf(lp, ip->format, "");
138 		lp += strlen(lp);
139 	}
140 	return(lp);
141 }
142 
143 char	*
144 gatherline(ip)
145 struct	openfile	*ip;
146 {
147 	char	s[BUFSIZ];
148 	register int	c;
149 	register char	*p;
150 	register char	*lp = linep;
151 	char	*end = s + BUFSIZ;
152 
153 	if (ip->eof)
154 		return(pad(ip));
155 	for (p = s; (c = fgetc(ip->fp)) != EOF && p < end; p++)
156 		if ((*p = c) == ip->eol)
157 			break;
158 	*p = '\0';
159 	if (c == EOF) {
160 		ip->eof = 1;
161 		if (ip->fp == stdin)
162 			fclose(stdin);
163 		morefiles--;
164 		return(pad(ip));
165 	}
166 	p = ip->sepstring;
167 	while (*p)
168 		*lp++ = *p++;
169 	sprintf(lp, ip->format, s);
170 	lp += strlen(lp);
171 	return(lp);
172 }
173 
174 error(msg, s)
175 char	*msg;
176 char	*s;
177 {
178 	char	buf[BUFSIZ];
179 
180 	setbuf(stderr, buf);
181 	fprintf(stderr, "lam: ");
182 	fprintf(stderr, msg, s);
183 	fprintf(stderr, "\nUsage:  lam [ -[fp] min.max ] [ -s sepstring ] [ -t c ] file ...\n");
184 	if (strncmp("lam - ", msg, 6) == 0)
185 		fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s",
186 			"-f min.max	field widths for file fragments\n",
187 			"-p min.max	like -f, but pad missing fragments\n",
188 			"-s sepstring	fragment separator\n",
189 			"-t c		input line terminator is c, no \\n after output lines\n",
190 			"Capitalized options affect more than one file.\n");
191 	exit(1);
192 }
193