getNAME.c revision 1.10 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