xref: /netbsd-src/libexec/getNAME/getNAME.c (revision 2a399c6883d870daece976daec6ffa7bb7f934ce)
1 /*	$NetBSD: getNAME.c,v 1.10 1997/12/22 20:02:33 christos Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997, Christos Zoulas
5  * Copyright (c) 1980, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  *	This product includes software developed by Christos Zoulas.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include <sys/cdefs.h>
39 #ifndef lint
40 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\n\
41 	The Regents of the University of California.  All rights reserved.\n");
42 #if 0
43 static char sccsid[] = "@(#)getNAME.c	8.1 (Berkeley) 6/30/93";
44 #else
45 __RCSID("$NetBSD: getNAME.c,v 1.10 1997/12/22 20:02:33 christos Exp $");
46 #endif
47 #endif /* not lint */
48 
49 /*
50  * Get name sections from manual pages.
51  *	-t	for building toc
52  *	-i	for building intro entries
53  *	-w	for querying type of manual source
54  *	other	apropos database
55  */
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <err.h>
60 
61 static int tocrc;
62 static int intro;
63 static int typeflag;
64 
65 #define SLOP 10	/* strlen(" () - ") < 10 */
66 
67 static char *linebuf = NULL;
68 static size_t maxlen = 0;
69 
70 
71 static void doname __P((char *));
72 static void dorefname __P((char *));
73 static void getfrom __P((char *));
74 static void oldman __P((char *, char *));
75 static void newman __P((char *, char *));
76 static void remcomma __P((char *, size_t *));
77 static void remquote __P((char *, size_t *));
78 static void fixxref __P((char *, size_t *));
79 static void split __P((char *, char *));
80 static void usage __P((void));
81 
82 int main __P((int, char *[]));
83 
84 int
85 main(argc, argv)
86 	int argc;
87 	char *argv[];
88 {
89 	int ch;
90 
91 	while ((ch = getopt(argc, argv, "itw")) != -1)
92 		switch (ch) {
93 		case 'i':
94 			intro = 1;
95 			break;
96 		case 't':
97 			tocrc = 1;
98 			break;
99 		case 'w':
100 			typeflag = 1;
101 			break;
102 		case '?':
103 		default:
104 			usage();
105 		}
106 	argc -= optind;
107 	argv += optind;
108 
109 	if (!*argv)
110 		usage();
111 
112 	for (; *argv; ++argv)
113 		getfrom(*argv);
114 	exit(0);
115 }
116 
117 void
118 getfrom(pathname)
119 	char *pathname;
120 {
121 	char *name;
122 	char *line;
123 	size_t len;
124 
125 	if (freopen(pathname, "r", stdin) == 0) {
126 		warn("Cannot open `%s'", pathname);
127 		return;
128 	}
129 	if ((name = strrchr(pathname, '/')) != NULL)
130 		name++;
131 	else
132 		name = pathname;
133 	for (;;) {
134 		if ((line = fgetln(stdin, &len)) == NULL) {
135 			if (typeflag)
136 				printf("%-60s\tUNKNOWN\n", pathname);
137 			return;
138 		}
139 		if (line[0] != '.')
140 			continue;
141 		if ((line[1] == 'T' && line[2] == 'H') ||
142 		    (line[1] == 't' && line[2] == 'h'))
143 			return oldman(pathname, name);
144 		if (line[1] == 'D' && line[2] == 't')
145 			return newman(pathname, name);
146 	}
147 }
148 
149 static void
150 oldman(pathname, name)
151 	char *pathname, *name;
152 {
153 	char *line, *ext, *s;
154 	size_t len, i, extlen;
155 	size_t curlen = 0;
156 
157 	if (typeflag) {
158 		printf("%-60s\tOLD\n", pathname);
159 		return;
160 	}
161 	for (;;) {
162 		if ((line = fgetln(stdin, &len)) == NULL)
163 			return;
164 		if (line[0] != '.')
165 			continue;
166 		if (line[1] == 'S' && line[2] == 'H')
167 			break;
168 		if (line[1] == 's' && line[2] == 'h')
169 			break;
170 	}
171 
172 	if (tocrc)
173 		doname(name);
174 
175 	for (i = 0;; i++) {
176 		if ((line = fgetln(stdin, &len)) == NULL)
177 			break;
178 		if (line[0] == '.') {
179 			if (line[1] == 'S' && line[2] == 'H')
180 				break;
181 			if (line[1] == 's' && line[2] == 'h')
182 				break;
183 		}
184 		if (line[len - 1] == '\n') {
185 			line[len - 1] = '\0';
186 			len--;
187 		}
188 		if ((ext = strrchr(name, '.')) != NULL) {
189 			ext++;
190 			extlen = strlen(ext);
191 		}
192 		else
193 			extlen = 0;
194 
195 		if (maxlen + extlen < curlen + len + SLOP) {
196 			maxlen = 2 * (curlen + len) + SLOP + extlen;
197 			if ((linebuf = realloc(linebuf, maxlen)) == NULL)
198 				err(1, "%s", "");
199 		}
200 		if (i != 0)
201 			linebuf[curlen++] = ' ';
202 		(void)memcpy(&linebuf[curlen], line, len);
203 		curlen += len;
204 		linebuf[curlen] = '\0';
205 
206 		/* change the \- into (N) - */
207 		if ((s = strstr(linebuf, "\\-")) != NULL) {
208 			(void)memmove(s + extlen + 3, s + 1,
209 			    curlen - (s + 1 - linebuf));
210 			curlen--;
211 			if (extlen) {
212 				*s++ = '(';
213 				while (*ext)
214 					*s++ = *ext++;
215 				*s++ = ')';
216 				*s++ = ' ';
217 				curlen += extlen + 3;
218 			}
219 			linebuf[curlen] = '\0';
220 		}
221 	}
222 
223 	if (intro)
224 		split(linebuf, name);
225 	else
226 		printf("%s\n", linebuf);
227 	return;
228 }
229 
230 static void
231 newman(pathname, name)
232 	char *pathname, *name;
233 {
234 	char *line, *ext;
235 	size_t len, i, extlen;
236 	size_t curlen = 0;
237 
238 	if (typeflag) {
239 		printf("%-60s\tNEW\n", pathname);
240 		return;
241 	}
242 	for (;;) {
243 		if ((line = fgetln(stdin, &len)) == NULL)
244 			return;
245 		if (line[0] != '.')
246 			continue;
247 		if (line[1] == 'S' && line[2] == 'h')
248 			break;
249 	}
250 
251 	if (tocrc)
252 		doname(name);
253 
254 	for (i = 0;; i++) {
255 		if ((line = fgetln(stdin, &len)) == NULL)
256 			break;
257 
258 		if (line[0] == '.') {
259 			if (line[1] == 'S' && line[2] == 'h')
260 				break;
261 		}
262 
263 		if (line[len - 1] == '\n') {
264 			line[len - 1] = '\0';
265 			len--;
266 		}
267 
268 		if ((ext = strrchr(name, '.')) != NULL) {
269 			ext++;
270 			extlen = strlen(ext);
271 		}
272 		else
273 			extlen = 0;
274 
275 		if (maxlen + extlen < curlen + len + SLOP) {
276 			maxlen = 2 * (curlen + len) + SLOP + extlen;
277 			if ((linebuf = realloc(linebuf, maxlen)) == NULL)
278 				err(1, "%s", "");
279 		}
280 
281 		if (i != 0)
282 			linebuf[curlen++] = ' ';
283 
284 		remcomma(line, &len);
285 
286 		if (line[0] != '.') {
287 			(void)memcpy(&linebuf[curlen], line, len);
288 			curlen += len;
289 		}
290 		else {
291 			remquote(line, &len);
292 			fixxref(line, &len);
293 
294 			/*
295 			 * Put section and dash between names and description.
296 			 */
297 			if (line[1] == 'N' && line[2] == 'd') {
298 				if (extlen) {
299 					linebuf[curlen++] = '(';
300 					while (*ext)
301 						linebuf[curlen++] = *ext++;
302 					linebuf[curlen++] = ')';
303 					linebuf[curlen++] = ' ';
304 				}
305 				linebuf[curlen++] = '-';
306 				linebuf[curlen++] = ' ';
307 			}
308 			/*
309 			 * Skip over macro names.
310 			 */
311 			if (len <= 4)
312 				continue;
313 			(void)memcpy(&linebuf[curlen], &line[4], len - 4);
314 			curlen += len - 4;
315 		}
316 	}
317 	linebuf[curlen] = '\0';
318 	if (intro)
319 		split(linebuf, name);
320 	else
321 		printf("%s\n", linebuf);
322 }
323 
324 /*
325  * convert " ," -> " "
326  */
327 static void
328 remcomma(line, len)
329 	char *line;
330 	size_t *len;
331 {
332 	char *pline = line, *loc;
333 	size_t plen = *len;
334 
335 	while ((loc = memchr(pline, ' ', plen)) != NULL) {
336 		plen -= loc - pline + 1;
337 		pline = loc;
338 		if (loc[1] == ',') {
339 			(void)memcpy(loc, &loc[1], plen);
340 			(*len)--;
341 		}
342 		else
343 			pline++;
344 	}
345 }
346 
347 /*
348  * Get rid of quotes in macros.
349  */
350 static
351 void remquote(line, len)
352 	char *line;
353 	size_t *len;
354 {
355 	char *loc;
356 	char *pline = &line[4];
357 	size_t plen = *len - 4;
358 
359 	if (*len < 4)
360 		return;
361 
362 	while ((loc = memchr(pline, '"', plen)) != NULL) {
363 		plen -= loc - pline + 1;
364 		pline = loc;
365 		(void)memcpy(loc, &loc[1], plen);
366 		(*len)--;
367 	}
368 }
369 
370 /*
371  * Handle cross references
372  */
373 static void
374 fixxref(line, len)
375 	char *line;
376 	size_t *len;
377 {
378 	char *loc;
379 	char *pline = &line[4];
380 	size_t plen = *len - 4;
381 
382 	if (*len < 4)
383 		return;
384 
385 	if (line[1] == 'X' && line[2] == 'r') {
386 		if ((loc = memchr(pline, ' ', plen)) != NULL) {
387 			*loc++ = '(';
388 			loc++;
389 			*loc++ = ')';
390 			*len = loc - line;
391 		}
392 	}
393 }
394 
395 static void
396 doname(name)
397 	char *name;
398 {
399 	char *dp = name, *ep;
400 
401 again:
402 	while (*dp && *dp != '.')
403 		putchar(*dp++);
404 	if (*dp)
405 		for (ep = dp+1; *ep; ep++)
406 			if (*ep == '.') {
407 				putchar(*dp++);
408 				goto again;
409 			}
410 	putchar('(');
411 	if (*dp)
412 		dp++;
413 	while (*dp)
414 		putchar (*dp++);
415 	putchar(')');
416 	putchar(' ');
417 }
418 
419 static void
420 split(line, name)
421 	char *line, *name;
422 {
423 	char *cp, *dp;
424 	char *sp, *sep;
425 
426 	cp = strchr(line, '-');
427 	if (cp == 0)
428 		return;
429 	sp = cp + 1;
430 	for (--cp; *cp == ' ' || *cp == '\t' || *cp == '\\'; cp--)
431 		;
432 	*++cp = '\0';
433 	while (*sp && (*sp == ' ' || *sp == '\t'))
434 		sp++;
435 	for (sep = "", dp = line; dp && *dp; dp = cp, sep = "\n") {
436 		cp = strchr(dp, ',');
437 		if (cp) {
438 			char *tp;
439 
440 			for (tp = cp - 1; *tp == ' ' || *tp == '\t'; tp--)
441 				;
442 			*++tp = '\0';
443 			for (++cp; *cp == ' ' || *cp == '\t'; cp++)
444 				;
445 		}
446 		printf("%s%s\t", sep, dp);
447 		dorefname(name);
448 		printf("\t%s", sp);
449 	}
450 }
451 
452 static void
453 dorefname(name)
454 	char *name;
455 {
456 	char *dp = name, *ep;
457 
458 again:
459 	while (*dp && *dp != '.')
460 		putchar(*dp++);
461 	if (*dp)
462 		for (ep = dp+1; *ep; ep++)
463 			if (*ep == '.') {
464 				putchar(*dp++);
465 				goto again;
466 			}
467 	putchar('.');
468 	if (*dp)
469 		dp++;
470 	while (*dp)
471 		putchar (*dp++);
472 }
473 
474 static void
475 usage()
476 {
477 	extern char *__progname;
478 	(void)fprintf(stderr, "Usage: %s [-itw] file ...\n", __progname);
479 	exit(1);
480 }
481