soelim.c revision 1.10 1 /* $NetBSD: soelim.c,v 1.10 2001/04/09 13:31:20 wiz Exp $ */
2
3 /*
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the University of
18 * California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36 #include <sys/cdefs.h>
37 #ifndef lint
38 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
39 The Regents of the University of California. All rights reserved.\n");
40 #endif /* not lint */
41
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)soelim.c 8.1 (Berkeley) 6/6/93";
45 #endif
46 __RCSID("$NetBSD: soelim.c,v 1.10 2001/04/09 13:31:20 wiz Exp $");
47 #endif /* not lint */
48
49 /*
50 * soelim - a filter to process n/troff input eliminating .so's
51 *
52 * Author: Bill Joy UCB July 8, 1977
53 *
54 * This program eliminates .so's from a n/troff input stream.
55 * It can be used to prepare safe input for submission to the
56 * phototypesetter since the software supporting the operator
57 * doesn't let him do chdir.
58 *
59 * This is a kludge and the operator should be given the
60 * ability to do chdir.
61 *
62 * This program is more generally useful, it turns out, because
63 * the program tbl doesn't understand ".so" directives.
64 */
65 #include <sys/param.h>
66 #include <err.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <unistd.h>
71
72 #define STDIN_NAME "-"
73
74 struct path {
75 char **list;
76 size_t n, c;
77 };
78
79 static int process(struct path *, const char *);
80 static void initpath(struct path *);
81 static void addpath(struct path *, const char *);
82 static FILE *openpath(struct path *, const char *, const char *);
83
84 int main(int, char **);
85
86
87 static void
88 initpath(struct path *p)
89 {
90 p->list = NULL;
91 p->n = p->c = 0;
92 }
93
94 static void
95 addpath(struct path *p, const char *dir)
96 {
97 if (p->list == NULL || p->n <= p->c - 2) {
98 p->n += 10;
99 p->list = realloc(p->list, p->n * sizeof(p->list[0]));
100 if (p->list == NULL)
101 err(1, NULL);
102 }
103
104 if ((p->list[p->c++] = strdup(dir)) == NULL)
105 err(1, NULL);
106
107 p->list[p->c] = NULL;
108 }
109
110 static FILE *
111 openpath(struct path *p, const char *name, const char *parm)
112 {
113 char filename[MAXPATHLEN];
114 const char *f;
115 FILE *fp;
116 size_t i;
117
118 if (*name == '/' || p->c == 0)
119 return fopen(name, parm);
120
121 for (i = 0; i < p->c; i++) {
122 if (p->list[i][0] == '\0')
123 f = name;
124 else {
125 (void)snprintf(filename, sizeof(filename), "%s/%s",
126 p->list[i], name);
127 f = filename;
128 }
129 if ((fp = fopen(f, parm)) != NULL)
130 return fp;
131 }
132 return NULL;
133 }
134
135 int
136 main(int argc, char *argv[])
137 {
138 struct path p;
139 int c;
140
141 initpath(&p);
142 addpath(&p, ".");
143
144 while ((c = getopt(argc, argv, "I:")) != -1)
145 switch (c) {
146 case 'I':
147 addpath(&p, optarg);
148 break;
149 default:
150 (void)fprintf(stderr,
151 "Usage: %s [-I<dir>] [files...]\n",
152 getprogname());
153 exit(1);
154 }
155
156 argc -= optind;
157 argv += optind;
158
159 if (argc == 0) {
160 (void)process(&p, STDIN_NAME);
161 exit(0);
162 }
163 do {
164 (void)process(&p, argv[0]);
165 argv++;
166 argc--;
167 } while (argc > 0);
168 exit(0);
169 }
170
171 int
172 process(struct path *p, const char *file)
173 {
174 char *cp;
175 int c;
176 char fname[BUFSIZ];
177 FILE *soee;
178 int isfile;
179
180 if (!strcmp(file, STDIN_NAME)) {
181 soee = stdin;
182 } else {
183 soee = openpath(p, file, "r");
184 if (soee == NULL) {
185 warn("Cannot open `%s'", file);
186 return(-1);
187 }
188 }
189 for (;;) {
190 c = getc(soee);
191 if (c == EOF)
192 break;
193 if (c != '.')
194 goto simple;
195 c = getc(soee);
196 if (c != 's') {
197 putchar('.');
198 goto simple;
199 }
200 c = getc(soee);
201 if (c != 'o') {
202 printf(".s");
203 goto simple;
204 }
205 do
206 c = getc(soee);
207 while (c == ' ' || c == '\t');
208 cp = fname;
209 isfile = 0;
210 for (;;) {
211 switch (c) {
212
213 case ' ':
214 case '\t':
215 case '\n':
216 case EOF:
217 goto donename;
218
219 default:
220 *cp++ = c;
221 c = getc(soee);
222 isfile++;
223 continue;
224 }
225 }
226 donename:
227 if (cp == fname) {
228 printf(".so");
229 goto simple;
230 }
231 *cp = 0;
232 if (process(p, fname) < 0)
233 if (isfile)
234 printf(".so %s\n", fname);
235 continue;
236 simple:
237 if (c == EOF)
238 break;
239 putchar(c);
240 if (c != '\n') {
241 c = getc(soee);
242 goto simple;
243 }
244 }
245 if (soee != stdin) {
246 fclose(soee);
247 }
248 return(0);
249 }
250