getNAME.c revision 1.12 1 /* $NetBSD: getNAME.c,v 1.12 1998/03/30 01:45:27 mrg 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.12 1998/03/30 01:45:27 mrg 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] == 'S' && line[2] == 'H')
181 break;
182 if (line[1] == 's' && line[2] == 'h')
183 break;
184 if (line[1] == 'P' && line[2] == 'P')
185 break;
186 }
187 if (line[len - 1] == '\n') {
188 line[len - 1] = '\0';
189 len--;
190 }
191 if ((ext = strrchr(name, '.')) != NULL) {
192 ext++;
193 extlen = strlen(ext);
194 }
195 else
196 extlen = 0;
197
198 if (maxlen + extlen < curlen + len + SLOP) {
199 maxlen = 2 * (curlen + len) + SLOP + extlen;
200 if ((linebuf = realloc(linebuf, maxlen)) == NULL)
201 err(1, "%s", "");
202 }
203 if (i != 0)
204 linebuf[curlen++] = ' ';
205 (void)memcpy(&linebuf[curlen], line, len);
206 curlen += len;
207 linebuf[curlen] = '\0';
208
209 /* change the \- into (N) - */
210 if ((s = strstr(linebuf, "\\-")) != NULL) {
211 (void)memmove(s + extlen + 3, s + 1,
212 curlen - (s + 1 - linebuf));
213 curlen--;
214 if (extlen) {
215 *s++ = '(';
216 while (*ext)
217 *s++ = *ext++;
218 *s++ = ')';
219 *s++ = ' ';
220 curlen += extlen + 3;
221 }
222 linebuf[curlen] = '\0';
223 }
224 }
225
226 if (intro)
227 split(linebuf, name);
228 else
229 printf("%s\n", linebuf);
230 return;
231 }
232
233 static void
234 newman(pathname, name)
235 char *pathname, *name;
236 {
237 char *line, *ext;
238 size_t len, i, extlen;
239 size_t curlen = 0;
240
241 if (typeflag) {
242 printf("%-60s\tNEW\n", pathname);
243 return;
244 }
245 for (;;) {
246 if ((line = fgetln(stdin, &len)) == NULL)
247 return;
248 if (line[0] != '.')
249 continue;
250 if (line[1] == 'S' && line[2] == 'h')
251 break;
252 }
253
254 if (tocrc)
255 doname(name);
256
257 for (i = 0;; i++) {
258 if ((line = fgetln(stdin, &len)) == NULL)
259 break;
260
261 if (line[0] == '.') {
262 if (line[1] == 'S' && line[2] == 'h')
263 break;
264 }
265
266 if (line[len - 1] == '\n') {
267 line[len - 1] = '\0';
268 len--;
269 }
270
271 if ((ext = strrchr(name, '.')) != NULL) {
272 ext++;
273 extlen = strlen(ext);
274 }
275 else
276 extlen = 0;
277
278 if (maxlen + extlen < curlen + len + SLOP) {
279 maxlen = 2 * (curlen + len) + SLOP + extlen;
280 if ((linebuf = realloc(linebuf, maxlen)) == NULL)
281 err(1, "%s", "");
282 }
283
284 if (i != 0)
285 linebuf[curlen++] = ' ';
286
287 remcomma(line, &len);
288
289 if (line[0] != '.') {
290 (void)memcpy(&linebuf[curlen], line, len);
291 curlen += len;
292 }
293 else {
294 remquote(line, &len);
295 fixxref(line, &len);
296
297 /*
298 * Put section and dash between names and description.
299 */
300 if (line[1] == 'N' && line[2] == 'd') {
301 if (extlen) {
302 linebuf[curlen++] = '(';
303 while (*ext)
304 linebuf[curlen++] = *ext++;
305 linebuf[curlen++] = ')';
306 linebuf[curlen++] = ' ';
307 }
308 linebuf[curlen++] = '-';
309 linebuf[curlen++] = ' ';
310 }
311 /*
312 * Skip over macro names.
313 */
314 if (len <= 4)
315 continue;
316 (void)memcpy(&linebuf[curlen], &line[4], len - 4);
317 curlen += len - 4;
318 }
319 }
320 linebuf[curlen] = '\0';
321 if (intro)
322 split(linebuf, name);
323 else
324 printf("%s\n", linebuf);
325 }
326
327 /*
328 * convert " ," -> " "
329 */
330 static void
331 remcomma(line, len)
332 char *line;
333 size_t *len;
334 {
335 char *pline = line, *loc;
336 size_t plen = *len;
337
338 while ((loc = memchr(pline, ' ', plen)) != NULL) {
339 plen -= loc - pline + 1;
340 pline = loc;
341 if (loc[1] == ',') {
342 (void)memcpy(loc, &loc[1], plen);
343 (*len)--;
344 }
345 else
346 pline++;
347 }
348 }
349
350 /*
351 * Get rid of quotes in macros.
352 */
353 static
354 void remquote(line, len)
355 char *line;
356 size_t *len;
357 {
358 char *loc;
359 char *pline = &line[4];
360 size_t plen = *len - 4;
361
362 if (*len < 4)
363 return;
364
365 while ((loc = memchr(pline, '"', plen)) != NULL) {
366 plen -= loc - pline + 1;
367 pline = loc;
368 (void)memcpy(loc, &loc[1], plen);
369 (*len)--;
370 }
371 }
372
373 /*
374 * Handle cross references
375 */
376 static void
377 fixxref(line, len)
378 char *line;
379 size_t *len;
380 {
381 char *loc;
382 char *pline = &line[4];
383 size_t plen = *len - 4;
384
385 if (*len < 4)
386 return;
387
388 if (line[1] == 'X' && line[2] == 'r') {
389 if ((loc = memchr(pline, ' ', plen)) != NULL) {
390 *loc++ = '(';
391 loc++;
392 *loc++ = ')';
393 *len = loc - line;
394 }
395 }
396 }
397
398 static void
399 doname(name)
400 char *name;
401 {
402 char *dp = name, *ep;
403
404 again:
405 while (*dp && *dp != '.')
406 putchar(*dp++);
407 if (*dp)
408 for (ep = dp+1; *ep; ep++)
409 if (*ep == '.') {
410 putchar(*dp++);
411 goto again;
412 }
413 putchar('(');
414 if (*dp)
415 dp++;
416 while (*dp)
417 putchar (*dp++);
418 putchar(')');
419 putchar(' ');
420 }
421
422 static void
423 split(line, name)
424 char *line, *name;
425 {
426 char *cp, *dp;
427 char *sp, *sep;
428
429 cp = strchr(line, '-');
430 if (cp == 0)
431 return;
432 sp = cp + 1;
433 for (--cp; *cp == ' ' || *cp == '\t' || *cp == '\\'; cp--)
434 ;
435 *++cp = '\0';
436 while (*sp && (*sp == ' ' || *sp == '\t'))
437 sp++;
438 for (sep = "", dp = line; dp && *dp; dp = cp, sep = "\n") {
439 cp = strchr(dp, ',');
440 if (cp) {
441 char *tp;
442
443 for (tp = cp - 1; *tp == ' ' || *tp == '\t'; tp--)
444 ;
445 *++tp = '\0';
446 for (++cp; *cp == ' ' || *cp == '\t'; cp++)
447 ;
448 }
449 printf("%s%s\t", sep, dp);
450 dorefname(name);
451 printf("\t%s", sp);
452 }
453 }
454
455 static void
456 dorefname(name)
457 char *name;
458 {
459 char *dp = name, *ep;
460
461 again:
462 while (*dp && *dp != '.')
463 putchar(*dp++);
464 if (*dp)
465 for (ep = dp+1; *ep; ep++)
466 if (*ep == '.') {
467 putchar(*dp++);
468 goto again;
469 }
470 putchar('.');
471 if (*dp)
472 dp++;
473 while (*dp)
474 putchar (*dp++);
475 }
476
477 static void
478 usage()
479 {
480 extern char *__progname;
481 (void)fprintf(stderr, "Usage: %s [-itw] file ...\n", __progname);
482 exit(1);
483 }
484