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