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