xref: /netbsd/usr.bin/soelim/soelim.c (revision bf9ec67e)
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