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