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