getNAME.c revision 1.13 1 /* $NetBSD: getNAME.c,v 1.13 1998/04/10 22:32:45 fair 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.13 1998/04/10 22:32:45 fair 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 <err.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
61
62 static int tocrc;
63 static int intro;
64 static int typeflag;
65
66 #define SLOP 10 /* strlen(" () - ") < 10 */
67
68 static char *linebuf = NULL;
69 static size_t maxlen = 0;
70
71
72 static void doname __P((char *));
73 static void dorefname __P((char *));
74 static void getfrom __P((char *));
75 static void oldman __P((char *, char *));
76 static void newman __P((char *, char *));
77 static void remcomma __P((char *, size_t *));
78 static void remquote __P((char *, size_t *));
79 static void fixxref __P((char *, size_t *));
80 static void split __P((char *, char *));
81 static void usage __P((void));
82
83 int main __P((int, char *[]));
84
85 int
86 main(argc, argv)
87 int argc;
88 char *argv[];
89 {
90 int ch;
91
92 while ((ch = getopt(argc, argv, "itw")) != -1)
93 switch (ch) {
94 case 'i':
95 intro = 1;
96 break;
97 case 't':
98 tocrc = 1;
99 break;
100 case 'w':
101 typeflag = 1;
102 break;
103 case '?':
104 default:
105 usage();
106 }
107 argc -= optind;
108 argv += optind;
109
110 if (!*argv)
111 usage();
112
113 for (; *argv; ++argv)
114 getfrom(*argv);
115 exit(0);
116 }
117
118 void
119 getfrom(pathname)
120 char *pathname;
121 {
122 char *name;
123 char *line;
124 size_t len;
125
126 if (freopen(pathname, "r", stdin) == 0) {
127 warn("Cannot open `%s'", pathname);
128 return;
129 }
130 if ((name = strrchr(pathname, '/')) != NULL)
131 name++;
132 else
133 name = pathname;
134 for (;;) {
135 if ((line = fgetln(stdin, &len)) == NULL) {
136 if (typeflag)
137 printf("%-60s\tUNKNOWN\n", pathname);
138 return;
139 }
140 if (line[0] != '.')
141 continue;
142 if ((line[1] == 'T' && line[2] == 'H') ||
143 (line[1] == 't' && line[2] == 'h'))
144 return oldman(pathname, name);
145 if (line[1] == 'D' && line[2] == 't')
146 return newman(pathname, name);
147 }
148 }
149
150 static void
151 oldman(pathname, name)
152 char *pathname, *name;
153 {
154 char *line, *ext, *s;
155 size_t len, i, extlen;
156 size_t curlen = 0;
157
158 if (typeflag) {
159 printf("%-60s\tOLD\n", pathname);
160 return;
161 }
162 for (;;) {
163 if ((line = fgetln(stdin, &len)) == NULL)
164 return;
165 if (line[0] != '.')
166 continue;
167 if (line[1] == 'S' && line[2] == 'H')
168 break;
169 if (line[1] == 's' && line[2] == 'h')
170 break;
171 }
172
173 if (tocrc)
174 doname(name);
175
176 for (i = 0;; i++) {
177 if ((line = fgetln(stdin, &len)) == NULL)
178 break;
179 if (line[0] == '.') {
180 if (line[1] == '\\' && line[2] == '"')
181 continue; /* [nt]roff comment */
182 if (line[1] == 'S' && line[2] == 'H')
183 break;
184 if (line[1] == 's' && line[2] == 'h')
185 break;
186 if (line[1] == 'P' && line[2] == 'P')
187 break;
188 }
189 if (line[len - 1] == '\n') {
190 line[len - 1] = '\0';
191 len--;
192 }
193 if ((ext = strrchr(name, '.')) != NULL) {
194 ext++;
195 extlen = strlen(ext);
196 }
197 else
198 extlen = 0;
199
200 if (maxlen + extlen < curlen + len + SLOP) {
201 maxlen = 2 * (curlen + len) + SLOP + extlen;
202 if ((linebuf = realloc(linebuf, maxlen)) == NULL)
203 err(1, "%s", "");
204 }
205 if (i != 0)
206 linebuf[curlen++] = ' ';
207 (void)memcpy(&linebuf[curlen], line, len);
208 curlen += len;
209 linebuf[curlen] = '\0';
210
211 /* change the \- into (N) - */
212 if ((s = strstr(linebuf, "\\-")) != NULL) {
213 (void)memmove(s + extlen + 3, s + 1,
214 curlen - (s + 1 - linebuf));
215 curlen--;
216 if (extlen) {
217 *s++ = '(';
218 while (*ext)
219 *s++ = *ext++;
220 *s++ = ')';
221 *s++ = ' ';
222 curlen += extlen + 3;
223 }
224 linebuf[curlen] = '\0';
225 }
226 }
227
228 if (intro)
229 split(linebuf, name);
230 else
231 printf("%s\n", linebuf);
232 return;
233 }
234
235 static void
236 newman(pathname, name)
237 char *pathname, *name;
238 {
239 char *line, *ext;
240 size_t len, i, extlen;
241 size_t curlen = 0;
242
243 if (typeflag) {
244 printf("%-60s\tNEW\n", pathname);
245 return;
246 }
247 for (;;) {
248 if ((line = fgetln(stdin, &len)) == NULL)
249 return;
250 if (line[0] != '.')
251 continue;
252 if (line[1] == 'S' && line[2] == 'h')
253 break;
254 }
255
256 if (tocrc)
257 doname(name);
258
259 for (i = 0;; i++) {
260 if ((line = fgetln(stdin, &len)) == NULL)
261 break;
262
263 if (line[0] == '.') {
264 if (line[1] == '\\' && line[2] == '"')
265 continue; /* [nt]roff comment */
266 if (line[1] == 'S' && line[2] == 'h')
267 break;
268 }
269
270 if (line[len - 1] == '\n') {
271 line[len - 1] = '\0';
272 len--;
273 }
274
275 if ((ext = strrchr(name, '.')) != NULL) {
276 ext++;
277 extlen = strlen(ext);
278 }
279 else
280 extlen = 0;
281
282 if (maxlen + extlen < curlen + len + SLOP) {
283 maxlen = 2 * (curlen + len) + SLOP + extlen;
284 if ((linebuf = realloc(linebuf, maxlen)) == NULL)
285 err(1, "%s", "");
286 }
287
288 if (i != 0)
289 linebuf[curlen++] = ' ';
290
291 remcomma(line, &len);
292
293 if (line[0] != '.') {
294 (void)memcpy(&linebuf[curlen], line, len);
295 curlen += len;
296 }
297 else {
298 remquote(line, &len);
299 fixxref(line, &len);
300
301 /*
302 * Put section and dash between names and description.
303 */
304 if (line[1] == 'N' && line[2] == 'd') {
305 if (extlen) {
306 linebuf[curlen++] = '(';
307 while (*ext)
308 linebuf[curlen++] = *ext++;
309 linebuf[curlen++] = ')';
310 linebuf[curlen++] = ' ';
311 }
312 linebuf[curlen++] = '-';
313 linebuf[curlen++] = ' ';
314 }
315 /*
316 * Skip over macro names.
317 */
318 if (len <= 4)
319 continue;
320 (void)memcpy(&linebuf[curlen], &line[4], len - 4);
321 curlen += len - 4;
322 }
323 }
324 linebuf[curlen] = '\0';
325 if (intro)
326 split(linebuf, name);
327 else
328 printf("%s\n", linebuf);
329 }
330
331 /*
332 * convert " ," -> " "
333 */
334 static void
335 remcomma(line, len)
336 char *line;
337 size_t *len;
338 {
339 char *pline = line, *loc;
340 size_t plen = *len;
341
342 while ((loc = memchr(pline, ' ', plen)) != NULL) {
343 plen -= loc - pline + 1;
344 pline = loc;
345 if (loc[1] == ',') {
346 (void)memcpy(loc, &loc[1], plen);
347 (*len)--;
348 }
349 else
350 pline++;
351 }
352 }
353
354 /*
355 * Get rid of quotes in macros.
356 */
357 static
358 void remquote(line, len)
359 char *line;
360 size_t *len;
361 {
362 char *loc;
363 char *pline = &line[4];
364 size_t plen = *len - 4;
365
366 if (*len < 4)
367 return;
368
369 while ((loc = memchr(pline, '"', plen)) != NULL) {
370 plen -= loc - pline + 1;
371 pline = loc;
372 (void)memcpy(loc, &loc[1], plen);
373 (*len)--;
374 }
375 }
376
377 /*
378 * Handle cross references
379 */
380 static void
381 fixxref(line, len)
382 char *line;
383 size_t *len;
384 {
385 char *loc;
386 char *pline = &line[4];
387 size_t plen = *len - 4;
388
389 if (*len < 4)
390 return;
391
392 if (line[1] == 'X' && line[2] == 'r') {
393 if ((loc = memchr(pline, ' ', plen)) != NULL) {
394 *loc++ = '(';
395 loc++;
396 *loc++ = ')';
397 *len = loc - line;
398 }
399 }
400 }
401
402 static void
403 doname(name)
404 char *name;
405 {
406 char *dp = name, *ep;
407
408 again:
409 while (*dp && *dp != '.')
410 putchar(*dp++);
411 if (*dp)
412 for (ep = dp+1; *ep; ep++)
413 if (*ep == '.') {
414 putchar(*dp++);
415 goto again;
416 }
417 putchar('(');
418 if (*dp)
419 dp++;
420 while (*dp)
421 putchar (*dp++);
422 putchar(')');
423 putchar(' ');
424 }
425
426 static void
427 split(line, name)
428 char *line, *name;
429 {
430 char *cp, *dp;
431 char *sp, *sep;
432
433 cp = strchr(line, '-');
434 if (cp == 0)
435 return;
436 sp = cp + 1;
437 for (--cp; *cp == ' ' || *cp == '\t' || *cp == '\\'; cp--)
438 ;
439 *++cp = '\0';
440 while (*sp && (*sp == ' ' || *sp == '\t'))
441 sp++;
442 for (sep = "", dp = line; dp && *dp; dp = cp, sep = "\n") {
443 cp = strchr(dp, ',');
444 if (cp) {
445 char *tp;
446
447 for (tp = cp - 1; *tp == ' ' || *tp == '\t'; tp--)
448 ;
449 *++tp = '\0';
450 for (++cp; *cp == ' ' || *cp == '\t'; cp++)
451 ;
452 }
453 printf("%s%s\t", sep, dp);
454 dorefname(name);
455 printf("\t%s", sp);
456 }
457 }
458
459 static void
460 dorefname(name)
461 char *name;
462 {
463 char *dp = name, *ep;
464
465 again:
466 while (*dp && *dp != '.')
467 putchar(*dp++);
468 if (*dp)
469 for (ep = dp+1; *ep; ep++)
470 if (*ep == '.') {
471 putchar(*dp++);
472 goto again;
473 }
474 putchar('.');
475 if (*dp)
476 dp++;
477 while (*dp)
478 putchar (*dp++);
479 }
480
481 static void
482 usage()
483 {
484 extern char *__progname;
485 (void)fprintf(stderr, "Usage: %s [-itw] file ...\n", __progname);
486 exit(1);
487 }
488