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
main(argc,argv)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
getargs(av)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 *
pad(ip)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 *
gatherline(ip)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
error(msg,s)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