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