xref: /netbsd-src/usr.bin/soelim/soelim.c (revision 39bbc68a3b8731308f39852383f5430560168a91)
1*39bbc68aSsevan /*	$NetBSD: soelim.c,v 1.15 2016/09/05 00:40:29 sevan Exp $	*/
25233fb40Sjtc 
361f28255Scgd /*
45233fb40Sjtc  * Copyright (c) 1980, 1993
55233fb40Sjtc  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
1589aaa1bbSagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
328976f097Slukem #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3498e5374cSlukem __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
3598e5374cSlukem  The Regents of the University of California.  All rights reserved.");
3661f28255Scgd #endif /* not lint */
3761f28255Scgd 
3861f28255Scgd #ifndef lint
395233fb40Sjtc #if 0
405233fb40Sjtc static char sccsid[] = "@(#)soelim.c	8.1 (Berkeley) 6/6/93";
415233fb40Sjtc #endif
42*39bbc68aSsevan __RCSID("$NetBSD: soelim.c,v 1.15 2016/09/05 00:40:29 sevan Exp $");
4361f28255Scgd #endif /* not lint */
4461f28255Scgd 
4561f28255Scgd /*
4661f28255Scgd  * soelim - a filter to process n/troff input eliminating .so's
4761f28255Scgd  *
4861f28255Scgd  * Author: Bill Joy UCB July 8, 1977
4961f28255Scgd  *
5061f28255Scgd  * This program eliminates .so's from a n/troff input stream.
5161f28255Scgd  * It can be used to prepare safe input for submission to the
5261f28255Scgd  * phototypesetter since the software supporting the operator
5361f28255Scgd  * doesn't let him do chdir.
5461f28255Scgd  *
5561f28255Scgd  * This is a kludge and the operator should be given the
5661f28255Scgd  * ability to do chdir.
5761f28255Scgd  *
5861f28255Scgd  * This program is more generally useful, it turns out, because
5961f28255Scgd  * the program tbl doesn't understand ".so" directives.
6061f28255Scgd  */
61b1d0822bSchristos #include <sys/param.h>
62b1d0822bSchristos #include <err.h>
63db49a933Sperry #include <stdio.h>
64db49a933Sperry #include <stdlib.h>
65db49a933Sperry #include <string.h>
66db49a933Sperry #include <unistd.h>
67b1d0822bSchristos 
6861f28255Scgd #define	STDIN_NAME	"-"
6961f28255Scgd 
70b1d0822bSchristos struct path {
71b1d0822bSchristos 	char **list;
72b1d0822bSchristos 	size_t n, c;
73b1d0822bSchristos };
74b1d0822bSchristos 
75c6a94bbfSwiz static int	 process(struct path *, const char *);
760d526c6dSwiz static void	 initpath(struct path *);
770d526c6dSwiz static void	 addpath(struct path *,  const char *);
780d526c6dSwiz static FILE	*openpath(struct path *, const char *, const char *);
79b1d0822bSchristos 
80b1d0822bSchristos 
81b1d0822bSchristos static void
initpath(struct path * p)820d526c6dSwiz initpath(struct path *p)
83b1d0822bSchristos {
84b1d0822bSchristos 	p->list = NULL;
85b1d0822bSchristos 	p->n = p->c = 0;
86b1d0822bSchristos }
87b1d0822bSchristos 
88b1d0822bSchristos static void
addpath(struct path * p,const char * dir)890d526c6dSwiz addpath(struct path *p, const char *dir)
90b1d0822bSchristos {
91d5250e4eSitojun 	char **n;
92d5250e4eSitojun 
93b1d0822bSchristos 	if (p->list == NULL || p->n <= p->c - 2) {
94d5250e4eSitojun 		n = realloc(p->list, (p->n + 10) * sizeof(p->list[0]));
95d5250e4eSitojun 		if (n == NULL)
9685cbf55dSdrochner 			err(1, NULL);
97d5250e4eSitojun 		p->list = n;
98d5250e4eSitojun 		p->n += 10;
99b1d0822bSchristos 	}
100b1d0822bSchristos 
101b1d0822bSchristos 	if ((p->list[p->c++] = strdup(dir)) == NULL)
10285cbf55dSdrochner 		err(1, NULL);
103b1d0822bSchristos 
104b1d0822bSchristos 	p->list[p->c] = NULL;
105b1d0822bSchristos }
106b1d0822bSchristos 
107b1d0822bSchristos static FILE *
openpath(struct path * p,const char * name,const char * parm)1080d526c6dSwiz openpath(struct path *p, const char *name, const char *parm)
109b1d0822bSchristos {
110b1d0822bSchristos 	char filename[MAXPATHLEN];
111b1d0822bSchristos 	const char *f;
112b1d0822bSchristos 	FILE *fp;
113b1d0822bSchristos 	size_t i;
114b1d0822bSchristos 
115b1d0822bSchristos 	if (*name == '/' || p->c == 0)
116b1d0822bSchristos 		return fopen(name, parm);
117b1d0822bSchristos 
118b1d0822bSchristos 	for (i = 0; i < p->c; i++) {
119b1d0822bSchristos 		if (p->list[i][0] == '\0')
120b1d0822bSchristos 			f = name;
121b1d0822bSchristos 		else {
122b1d0822bSchristos 			(void)snprintf(filename, sizeof(filename), "%s/%s",
123b1d0822bSchristos 			    p->list[i], name);
124b1d0822bSchristos 			f = filename;
125b1d0822bSchristos 		}
126b1d0822bSchristos 		if ((fp = fopen(f, parm)) != NULL)
127b1d0822bSchristos 			return fp;
128b1d0822bSchristos 	}
129b1d0822bSchristos 	return NULL;
130b1d0822bSchristos }
1318976f097Slukem 
1328976f097Slukem int
main(int argc,char * argv[])1330d526c6dSwiz main(int argc, char *argv[])
13461f28255Scgd {
135b1d0822bSchristos 	struct path p;
136b1d0822bSchristos 	int c;
13761f28255Scgd 
138b1d0822bSchristos 	initpath(&p);
139b1d0822bSchristos 	addpath(&p, ".");
140b1d0822bSchristos 
141b1d0822bSchristos 	while ((c = getopt(argc, argv, "I:")) != -1)
142b1d0822bSchristos 		switch (c) {
143b1d0822bSchristos 		case 'I':
144b1d0822bSchristos 			addpath(&p, optarg);
145b1d0822bSchristos 			break;
146b1d0822bSchristos 		default:
147b1d0822bSchristos 			(void)fprintf(stderr,
148b635f565Sjmmv 			    "usage: %s [-I<dir>] [files...]\n",
149a8ec668dScgd 			    getprogname());
150b1d0822bSchristos 			exit(1);
151b1d0822bSchristos 		}
152b1d0822bSchristos 
153b1d0822bSchristos 	argc -= optind;
154b1d0822bSchristos 	argv += optind;
155b1d0822bSchristos 
15661f28255Scgd 	if (argc == 0) {
157b1d0822bSchristos 		(void)process(&p, STDIN_NAME);
15861f28255Scgd 		exit(0);
15961f28255Scgd 	}
16061f28255Scgd 	do {
161b1d0822bSchristos 		(void)process(&p, argv[0]);
16261f28255Scgd 		argv++;
16361f28255Scgd 		argc--;
16461f28255Scgd 	} while (argc > 0);
16561f28255Scgd 	exit(0);
16661f28255Scgd }
16761f28255Scgd 
1688976f097Slukem int
process(struct path * p,const char * file)169c6a94bbfSwiz process(struct path *p, const char *file)
17061f28255Scgd {
1718976f097Slukem 	char *cp;
1728976f097Slukem 	int c;
17361f28255Scgd 	char fname[BUFSIZ];
17461f28255Scgd 	FILE *soee;
17561f28255Scgd 	int isfile;
17661f28255Scgd 
17761f28255Scgd 	if (!strcmp(file, STDIN_NAME)) {
17861f28255Scgd 		soee = stdin;
17961f28255Scgd 	} else {
180b1d0822bSchristos 		soee = openpath(p, file, "r");
18161f28255Scgd 		if (soee == NULL) {
182b1d0822bSchristos 			warn("Cannot open `%s'", file);
18361f28255Scgd 			return(-1);
18461f28255Scgd 		}
18561f28255Scgd 	}
18661f28255Scgd 	for (;;) {
18761f28255Scgd 		c = getc(soee);
18861f28255Scgd 		if (c == EOF)
18961f28255Scgd 			break;
19061f28255Scgd 		if (c != '.')
19161f28255Scgd 			goto simple;
19261f28255Scgd 		c = getc(soee);
19361f28255Scgd 		if (c != 's') {
19461f28255Scgd 			putchar('.');
19561f28255Scgd 			goto simple;
19661f28255Scgd 		}
19761f28255Scgd 		c = getc(soee);
19861f28255Scgd 		if (c != 'o') {
19961f28255Scgd 			printf(".s");
20061f28255Scgd 			goto simple;
20161f28255Scgd 		}
20261f28255Scgd 		do
20361f28255Scgd 			c = getc(soee);
20461f28255Scgd 		while (c == ' ' || c == '\t');
20561f28255Scgd 		cp = fname;
20661f28255Scgd 		isfile = 0;
20761f28255Scgd 		for (;;) {
20861f28255Scgd 			switch (c) {
20961f28255Scgd 
21061f28255Scgd 			case ' ':
21161f28255Scgd 			case '\t':
21261f28255Scgd 			case '\n':
21361f28255Scgd 			case EOF:
21461f28255Scgd 				goto donename;
21561f28255Scgd 
21661f28255Scgd 			default:
21761f28255Scgd 				*cp++ = c;
21861f28255Scgd 				c = getc(soee);
21961f28255Scgd 				isfile++;
22061f28255Scgd 				continue;
22161f28255Scgd 			}
22261f28255Scgd 		}
22361f28255Scgd donename:
22461f28255Scgd 		if (cp == fname) {
22561f28255Scgd 			printf(".so");
22661f28255Scgd 			goto simple;
22761f28255Scgd 		}
22861f28255Scgd 		*cp = 0;
229b1d0822bSchristos 		if (process(p, fname) < 0)
23061f28255Scgd 			if (isfile)
23161f28255Scgd 				printf(".so %s\n", fname);
23261f28255Scgd 		continue;
23361f28255Scgd simple:
23461f28255Scgd 		if (c == EOF)
23561f28255Scgd 			break;
23661f28255Scgd 		putchar(c);
23761f28255Scgd 		if (c != '\n') {
23861f28255Scgd 			c = getc(soee);
23961f28255Scgd 			goto simple;
24061f28255Scgd 		}
24161f28255Scgd 	}
24261f28255Scgd 	if (soee != stdin) {
24361f28255Scgd 		fclose(soee);
24461f28255Scgd 	}
24561f28255Scgd 	return(0);
24661f28255Scgd }
247