xref: /netbsd-src/usr.bin/soelim/soelim.c (revision 481fca6e59249d8ffcf24fef7cfbe7b131bfb080)
1 /*	$NetBSD: soelim.c,v 1.7 1999/11/09 15:06:36 drochner 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.7 1999/11/09 15:06:36 drochner 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 __P((struct path *, char *));
80 static void	 initpath __P((struct path *));
81 static void	 addpath __P((struct path *,  const char *));
82 static FILE	*openpath __P((struct path *, const char *, const char *));
83 
84 int	main __P((int, char **));
85 
86 
87 static void
88 initpath(p)
89 	struct path *p;
90 {
91 	p->list = NULL;
92 	p->n = p->c = 0;
93 }
94 
95 static void
96 addpath(p, dir)
97 	struct path *p;
98 	const char *dir;
99 {
100 	if (p->list == NULL || p->n <= p->c - 2) {
101 		p->n += 10;
102 		p->list = realloc(p->list, p->n * sizeof(p->list[0]));
103 		if (p->list == NULL)
104 			err(1, NULL);
105 	}
106 
107 	if ((p->list[p->c++] = strdup(dir)) == NULL)
108 		err(1, NULL);
109 
110 	p->list[p->c] = NULL;
111 }
112 
113 static FILE *
114 openpath(p, name, parm)
115 	struct path *p;
116 	const char *name;
117 	const char *parm;
118 {
119 	char filename[MAXPATHLEN];
120 	const char *f;
121 	FILE *fp;
122 	size_t i;
123 
124 	if (*name == '/' || p->c == 0)
125 		return fopen(name, parm);
126 
127 	for (i = 0; i < p->c; i++) {
128 		if (p->list[i][0] == '\0')
129 			f = name;
130 		else {
131 			(void)snprintf(filename, sizeof(filename), "%s/%s",
132 			    p->list[i], name);
133 			f = filename;
134 		}
135 		if ((fp = fopen(f, parm)) != NULL)
136 			return fp;
137 	}
138 	return NULL;
139 }
140 
141 int
142 main(argc, argv)
143 	int argc;
144 	char *argv[];
145 {
146 	extern char *__progname;
147 	struct path p;
148 	int c;
149 
150 	initpath(&p);
151 	addpath(&p, ".");
152 
153 	while ((c = getopt(argc, argv, "I:")) != -1)
154 		switch (c) {
155 		case 'I':
156 			addpath(&p, optarg);
157 			break;
158 		default:
159 			(void)fprintf(stderr,
160 			    "Usage: %s [-I<dir>] [files...]\n", __progname);
161 			exit(1);
162 		}
163 
164 	argc -= optind;
165 	argv += optind;
166 
167 	if (argc == 0) {
168 		(void)process(&p, STDIN_NAME);
169 		exit(0);
170 	}
171 	do {
172 		(void)process(&p, argv[0]);
173 		argv++;
174 		argc--;
175 	} while (argc > 0);
176 	exit(0);
177 }
178 
179 int
180 process(p, file)
181 	struct path *p;
182 	char *file;
183 {
184 	char *cp;
185 	int c;
186 	char fname[BUFSIZ];
187 	FILE *soee;
188 	int isfile;
189 
190 	if (!strcmp(file, STDIN_NAME)) {
191 		soee = stdin;
192 	} else {
193 		soee = openpath(p, file, "r");
194 		if (soee == NULL) {
195 			warn("Cannot open `%s'", file);
196 			return(-1);
197 		}
198 	}
199 	for (;;) {
200 		c = getc(soee);
201 		if (c == EOF)
202 			break;
203 		if (c != '.')
204 			goto simple;
205 		c = getc(soee);
206 		if (c != 's') {
207 			putchar('.');
208 			goto simple;
209 		}
210 		c = getc(soee);
211 		if (c != 'o') {
212 			printf(".s");
213 			goto simple;
214 		}
215 		do
216 			c = getc(soee);
217 		while (c == ' ' || c == '\t');
218 		cp = fname;
219 		isfile = 0;
220 		for (;;) {
221 			switch (c) {
222 
223 			case ' ':
224 			case '\t':
225 			case '\n':
226 			case EOF:
227 				goto donename;
228 
229 			default:
230 				*cp++ = c;
231 				c = getc(soee);
232 				isfile++;
233 				continue;
234 			}
235 		}
236 donename:
237 		if (cp == fname) {
238 			printf(".so");
239 			goto simple;
240 		}
241 		*cp = 0;
242 		if (process(p, fname) < 0)
243 			if (isfile)
244 				printf(".so %s\n", fname);
245 		continue;
246 simple:
247 		if (c == EOF)
248 			break;
249 		putchar(c);
250 		if (c != '\n') {
251 			c = getc(soee);
252 			goto simple;
253 		}
254 	}
255 	if (soee != stdin) {
256 		fclose(soee);
257 	}
258 	return(0);
259 }
260