xref: /freebsd/contrib/mandoc/soelim.c (revision 61d06d6bd19dafe8ea971dd43e8328fa1b473456)
1*61d06d6bSBaptiste Daroussin /*	$Id: soelim.c,v 1.5 2015/11/07 14:22:29 schwarze Exp $	*/
2*61d06d6bSBaptiste Daroussin /*
3*61d06d6bSBaptiste Daroussin  * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
4*61d06d6bSBaptiste Daroussin  * All rights reserved.
5*61d06d6bSBaptiste Daroussin  *
6*61d06d6bSBaptiste Daroussin  * Redistribution and use in source and binary forms, with or without
7*61d06d6bSBaptiste Daroussin  * modification, are permitted provided that the following conditions
8*61d06d6bSBaptiste Daroussin  * are met:
9*61d06d6bSBaptiste Daroussin  * 1. Redistributions of source code must retain the above copyright
10*61d06d6bSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer
11*61d06d6bSBaptiste Daroussin  *    in this position and unchanged.
12*61d06d6bSBaptiste Daroussin  * 2. Redistributions in binary form must reproduce the above copyright
13*61d06d6bSBaptiste Daroussin  *    notice, this list of conditions and the following disclaimer in the
14*61d06d6bSBaptiste Daroussin  *    documentation and/or other materials provided with the distribution.
15*61d06d6bSBaptiste Daroussin  *
16*61d06d6bSBaptiste Daroussin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17*61d06d6bSBaptiste Daroussin  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18*61d06d6bSBaptiste Daroussin  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19*61d06d6bSBaptiste Daroussin  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20*61d06d6bSBaptiste Daroussin  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21*61d06d6bSBaptiste Daroussin  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22*61d06d6bSBaptiste Daroussin  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23*61d06d6bSBaptiste Daroussin  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*61d06d6bSBaptiste Daroussin  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25*61d06d6bSBaptiste Daroussin  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*61d06d6bSBaptiste Daroussin  */
27*61d06d6bSBaptiste Daroussin #include "config.h"
28*61d06d6bSBaptiste Daroussin 
29*61d06d6bSBaptiste Daroussin #include <sys/types.h>
30*61d06d6bSBaptiste Daroussin 
31*61d06d6bSBaptiste Daroussin #include <ctype.h>
32*61d06d6bSBaptiste Daroussin #if HAVE_ERR
33*61d06d6bSBaptiste Daroussin #include <err.h>
34*61d06d6bSBaptiste Daroussin #endif
35*61d06d6bSBaptiste Daroussin #include <limits.h>
36*61d06d6bSBaptiste Daroussin #include <stdio.h>
37*61d06d6bSBaptiste Daroussin #include <stdlib.h>
38*61d06d6bSBaptiste Daroussin #include <string.h>
39*61d06d6bSBaptiste Daroussin #if HAVE_STRINGLIST
40*61d06d6bSBaptiste Daroussin #include <stringlist.h>
41*61d06d6bSBaptiste Daroussin #else
42*61d06d6bSBaptiste Daroussin #include "compat_stringlist.h"
43*61d06d6bSBaptiste Daroussin #endif
44*61d06d6bSBaptiste Daroussin #include <unistd.h>
45*61d06d6bSBaptiste Daroussin 
46*61d06d6bSBaptiste Daroussin #define C_OPTION 0x1
47*61d06d6bSBaptiste Daroussin 
48*61d06d6bSBaptiste Daroussin static StringList *includes;
49*61d06d6bSBaptiste Daroussin 
50*61d06d6bSBaptiste Daroussin static void
51*61d06d6bSBaptiste Daroussin usage(void)
52*61d06d6bSBaptiste Daroussin {
53*61d06d6bSBaptiste Daroussin 
54*61d06d6bSBaptiste Daroussin 	fprintf(stderr, "usage: soelim [-Crtv] [-I dir] [files]\n");
55*61d06d6bSBaptiste Daroussin 
56*61d06d6bSBaptiste Daroussin 	exit(EXIT_FAILURE);
57*61d06d6bSBaptiste Daroussin }
58*61d06d6bSBaptiste Daroussin 
59*61d06d6bSBaptiste Daroussin static FILE *
60*61d06d6bSBaptiste Daroussin soelim_fopen(const char *name)
61*61d06d6bSBaptiste Daroussin {
62*61d06d6bSBaptiste Daroussin 	FILE *f;
63*61d06d6bSBaptiste Daroussin 	char path[PATH_MAX];
64*61d06d6bSBaptiste Daroussin 	size_t i;
65*61d06d6bSBaptiste Daroussin 
66*61d06d6bSBaptiste Daroussin 	if (strcmp(name, "-") == 0)
67*61d06d6bSBaptiste Daroussin 		return (stdin);
68*61d06d6bSBaptiste Daroussin 
69*61d06d6bSBaptiste Daroussin 	if ((f = fopen(name, "r")) != NULL)
70*61d06d6bSBaptiste Daroussin 		return (f);
71*61d06d6bSBaptiste Daroussin 
72*61d06d6bSBaptiste Daroussin 	if (*name == '/') {
73*61d06d6bSBaptiste Daroussin 		warn("can't open '%s'", name);
74*61d06d6bSBaptiste Daroussin 		return (NULL);
75*61d06d6bSBaptiste Daroussin 	}
76*61d06d6bSBaptiste Daroussin 
77*61d06d6bSBaptiste Daroussin 	for (i = 0; i < includes->sl_cur; i++) {
78*61d06d6bSBaptiste Daroussin 		snprintf(path, sizeof(path), "%s/%s", includes->sl_str[i],
79*61d06d6bSBaptiste Daroussin 		    name);
80*61d06d6bSBaptiste Daroussin 		if ((f = fopen(path, "r")) != NULL)
81*61d06d6bSBaptiste Daroussin 			return (f);
82*61d06d6bSBaptiste Daroussin 	}
83*61d06d6bSBaptiste Daroussin 
84*61d06d6bSBaptiste Daroussin 	warn("can't open '%s'", name);
85*61d06d6bSBaptiste Daroussin 
86*61d06d6bSBaptiste Daroussin 	return (f);
87*61d06d6bSBaptiste Daroussin }
88*61d06d6bSBaptiste Daroussin 
89*61d06d6bSBaptiste Daroussin static int
90*61d06d6bSBaptiste Daroussin soelim_file(FILE *f, int flag)
91*61d06d6bSBaptiste Daroussin {
92*61d06d6bSBaptiste Daroussin 	char *line = NULL;
93*61d06d6bSBaptiste Daroussin 	char *walk, *cp;
94*61d06d6bSBaptiste Daroussin 	size_t linecap = 0;
95*61d06d6bSBaptiste Daroussin 	ssize_t linelen;
96*61d06d6bSBaptiste Daroussin 
97*61d06d6bSBaptiste Daroussin 	if (f == NULL)
98*61d06d6bSBaptiste Daroussin 		return (1);
99*61d06d6bSBaptiste Daroussin 
100*61d06d6bSBaptiste Daroussin 	while ((linelen = getline(&line, &linecap, f)) > 0) {
101*61d06d6bSBaptiste Daroussin 		if (strncmp(line, ".so", 3) != 0) {
102*61d06d6bSBaptiste Daroussin 			printf("%s", line);
103*61d06d6bSBaptiste Daroussin 			continue;
104*61d06d6bSBaptiste Daroussin 		}
105*61d06d6bSBaptiste Daroussin 
106*61d06d6bSBaptiste Daroussin 		walk = line + 3;
107*61d06d6bSBaptiste Daroussin 		if (!isspace(*walk) && ((flag & C_OPTION) == 0)) {
108*61d06d6bSBaptiste Daroussin 			printf("%s", line);
109*61d06d6bSBaptiste Daroussin 			continue;
110*61d06d6bSBaptiste Daroussin 		}
111*61d06d6bSBaptiste Daroussin 
112*61d06d6bSBaptiste Daroussin 		while (isspace(*walk))
113*61d06d6bSBaptiste Daroussin 			walk++;
114*61d06d6bSBaptiste Daroussin 
115*61d06d6bSBaptiste Daroussin 		cp = walk;
116*61d06d6bSBaptiste Daroussin 		while (*cp != '\0' && !isspace(*cp))
117*61d06d6bSBaptiste Daroussin 			cp++;
118*61d06d6bSBaptiste Daroussin 		*cp = 0;
119*61d06d6bSBaptiste Daroussin 		if (cp < line + linelen)
120*61d06d6bSBaptiste Daroussin 			cp++;
121*61d06d6bSBaptiste Daroussin 
122*61d06d6bSBaptiste Daroussin 		if (*walk == '\0') {
123*61d06d6bSBaptiste Daroussin 			printf("%s", line);
124*61d06d6bSBaptiste Daroussin 			continue;
125*61d06d6bSBaptiste Daroussin 		}
126*61d06d6bSBaptiste Daroussin 		if (soelim_file(soelim_fopen(walk), flag) == 1) {
127*61d06d6bSBaptiste Daroussin 			free(line);
128*61d06d6bSBaptiste Daroussin 			return (1);
129*61d06d6bSBaptiste Daroussin 		}
130*61d06d6bSBaptiste Daroussin 		if (*cp != '\0')
131*61d06d6bSBaptiste Daroussin 			printf("%s", cp);
132*61d06d6bSBaptiste Daroussin 	}
133*61d06d6bSBaptiste Daroussin 
134*61d06d6bSBaptiste Daroussin 	free(line);
135*61d06d6bSBaptiste Daroussin 	fclose(f);
136*61d06d6bSBaptiste Daroussin 
137*61d06d6bSBaptiste Daroussin 	return (0);
138*61d06d6bSBaptiste Daroussin }
139*61d06d6bSBaptiste Daroussin 
140*61d06d6bSBaptiste Daroussin int
141*61d06d6bSBaptiste Daroussin main(int argc, char **argv)
142*61d06d6bSBaptiste Daroussin {
143*61d06d6bSBaptiste Daroussin 	int ch, i;
144*61d06d6bSBaptiste Daroussin 	int ret = 0;
145*61d06d6bSBaptiste Daroussin 	int flags = 0;
146*61d06d6bSBaptiste Daroussin 
147*61d06d6bSBaptiste Daroussin 	includes = sl_init();
148*61d06d6bSBaptiste Daroussin 	if (includes == NULL)
149*61d06d6bSBaptiste Daroussin 		err(EXIT_FAILURE, "sl_init()");
150*61d06d6bSBaptiste Daroussin 
151*61d06d6bSBaptiste Daroussin 	while ((ch = getopt(argc, argv, "CrtvI:")) != -1) {
152*61d06d6bSBaptiste Daroussin 		switch (ch) {
153*61d06d6bSBaptiste Daroussin 		case 'C':
154*61d06d6bSBaptiste Daroussin 			flags |= C_OPTION;
155*61d06d6bSBaptiste Daroussin 			break;
156*61d06d6bSBaptiste Daroussin 		case 'r':
157*61d06d6bSBaptiste Daroussin 		case 'v':
158*61d06d6bSBaptiste Daroussin 		case 't':
159*61d06d6bSBaptiste Daroussin 			/* stub compatibility with groff's soelim */
160*61d06d6bSBaptiste Daroussin 			break;
161*61d06d6bSBaptiste Daroussin 		case 'I':
162*61d06d6bSBaptiste Daroussin 			sl_add(includes, optarg);
163*61d06d6bSBaptiste Daroussin 			break;
164*61d06d6bSBaptiste Daroussin 		default:
165*61d06d6bSBaptiste Daroussin 			sl_free(includes, 0);
166*61d06d6bSBaptiste Daroussin 			usage();
167*61d06d6bSBaptiste Daroussin 		}
168*61d06d6bSBaptiste Daroussin 	}
169*61d06d6bSBaptiste Daroussin 
170*61d06d6bSBaptiste Daroussin 	argc -= optind;
171*61d06d6bSBaptiste Daroussin 	argv += optind;
172*61d06d6bSBaptiste Daroussin 
173*61d06d6bSBaptiste Daroussin 	if (argc == 0)
174*61d06d6bSBaptiste Daroussin 		ret = soelim_file(stdin, flags);
175*61d06d6bSBaptiste Daroussin 
176*61d06d6bSBaptiste Daroussin 	for (i = 0; i < argc; i++)
177*61d06d6bSBaptiste Daroussin 		ret = soelim_file(soelim_fopen(argv[i]), flags);
178*61d06d6bSBaptiste Daroussin 
179*61d06d6bSBaptiste Daroussin 	sl_free(includes, 0);
180*61d06d6bSBaptiste Daroussin 
181*61d06d6bSBaptiste Daroussin 	return (ret);
182*61d06d6bSBaptiste Daroussin }
183