Initial import from FreeBSD RELENG_4:
[dragonfly.git] / libexec / getNAME / getNAME.c
1 /*-
2  * Copyright (c) 1980, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static const char copyright[] =
36 "@(#) Copyright (c) 1980, 1993\n\
37         The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)getNAME.c   8.1 (Berkeley) 6/30/93";
43 #endif
44 static const char rcsid[] =
45   "$FreeBSD: src/libexec/getNAME/getNAME.c,v 1.7 1999/08/28 00:09:33 peter Exp $";
46 #endif /* not lint */
47
48 /*
49  * Get name sections from manual pages.
50  *      -t      for building toc
51  *      -i      for building intro entries
52  *      other   apropos database
53  */
54 #include <err.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
59
60 int tocrc;
61 int intro;
62 int typeflag;
63
64 void doname __P((char *));
65 void dorefname __P((char *));
66 void getfrom __P((char *));
67 void split __P((char *, char *));
68 void trimln __P((char *));
69 static void usage __P((void));
70
71 int
72 main(argc, argv)
73         int argc;
74         char *argv[];
75 {
76         int ch;
77
78         while ((ch = getopt(argc, argv, "itw")) != -1)
79                 switch(ch) {
80                 case 'i':
81                         intro = 1;
82                         break;
83                 case 't':
84                         tocrc = 1;
85                         break;
86                 case 'w':
87                         typeflag = 1;
88                         break;
89                 default:
90                         usage();
91                 }
92         argc -= optind;
93         argv += optind;
94
95         if (!*argv)
96                 usage();
97
98         for (; *argv; ++argv)
99                 getfrom(*argv);
100         exit(0);
101 }
102
103 void
104 getfrom(pathname)
105         char *pathname;
106 {
107         int i = 0;
108         char *name, *loc;
109         char headbuf[BUFSIZ];
110         char linbuf[BUFSIZ];
111
112         if (freopen(pathname, "r", stdin) == 0) {
113                 warn("%s", pathname);
114                 return;
115         }
116         if ((name = strrchr(pathname, '/')))
117                 name++;
118         else
119                 name = pathname;
120         for (;;) {
121                 if (fgets(headbuf, sizeof headbuf, stdin) == NULL) {
122                         if (typeflag)
123                                 printf("%-60s   UNKNOWN\n", pathname);
124                         return;
125                 }
126                 if (headbuf[0] != '.')
127                         continue;
128                 if ((headbuf[1] == 'T' && headbuf[2] == 'H') ||
129                     (headbuf[1] == 't' && headbuf[2] == 'h'))
130                         break;
131                 if (headbuf[1] == 'D' && headbuf[2] == 't') {
132                         if (typeflag) {
133                                 printf("%-60s   NEW\n", pathname);
134                                 return;
135                         }
136                         goto newman;
137                 }
138         }
139         if (typeflag) {
140                 printf("%-60s   OLD\n", pathname);
141                 return;
142         }
143         for (;;) {
144                 if (fgets(linbuf, sizeof linbuf, stdin) == NULL)
145                         return;
146                 if (linbuf[0] != '.')
147                         continue;
148                 if (linbuf[1] == 'S' && linbuf[2] == 'H')
149                         break;
150                 if (linbuf[1] == 's' && linbuf[2] == 'h')
151                         break;
152         }
153         trimln(headbuf);
154         if (tocrc)
155                 doname(name);
156         if (!tocrc && !intro)
157                 printf("%s\t", headbuf);
158         linbuf[0] = '\0';
159         for (;;) {
160                 if (fgets(headbuf, sizeof headbuf, stdin) == NULL)
161                         break;
162                 if (headbuf[0] == '.') {
163                         if (headbuf[1] == 'S' && headbuf[2] == 'H')
164                                 break;
165                         if (headbuf[1] == 's' && headbuf[2] == 'h')
166                                 break;
167                 }
168                 if (i != 0)
169                         strcat(linbuf, " ");
170                 i++;
171                 trimln(headbuf);
172                 strcat(linbuf, headbuf);
173         }
174         if (intro)
175                 split(linbuf, name);
176         else
177                 printf("%s\n", linbuf);
178         return;
179
180 newman:
181         for (;;) {
182                 if (fgets(linbuf, sizeof linbuf, stdin) == NULL)
183                         return;
184                 if (linbuf[0] != '.')
185                         continue;
186                 if (linbuf[1] == 'S' && linbuf[2] == 'h')
187                         break;
188         }
189         trimln(headbuf);
190         if (tocrc)
191                 doname(name);
192         if (!tocrc && !intro)
193                 printf(".TH%s\t", &headbuf[3]);
194         linbuf[0] = '\0';
195         for (;;) {
196                 if (fgets(headbuf, sizeof headbuf, stdin) == NULL)
197                         break;
198                 if (headbuf[0] == '.') {
199                         if (headbuf[1] == 'S' && headbuf[2] == 'h')
200                                 break;
201                 }
202                 if (i != 0)
203                         strcat(linbuf, " ");
204                 i++;
205                 trimln(headbuf);
206                 for (loc = strchr(headbuf, ' '); loc; loc = strchr(loc, ' '))
207                         if (loc[1] == ',')
208                                 strcpy(loc, &loc[1]);
209                         else
210                                 loc++;
211                 if (headbuf[0] != '.') {
212                         strcat(linbuf, headbuf);
213                 } else {
214                         /*
215                          * Get rid of quotes in macros.
216                          */
217                         for (loc = strchr(&headbuf[4], '"'); loc; ) {
218                                 strcpy(loc, &loc[1]);
219                                 loc = strchr(loc, '"');
220                         }
221                         /*
222                          * Handle cross references
223                          */
224                         if (headbuf[1] == 'X' && headbuf[2] == 'r') {
225                                 for (loc = &headbuf[4]; *loc != ' '; loc++)
226                                         continue;
227                                 loc[0] = '(';
228                                 loc[2] = ')';
229                                 loc[3] = '\0';
230                         }
231                         /*
232                          * Put dash between names and description.
233                          */
234                         if (headbuf[1] == 'N' && headbuf[2] == 'd')
235                                 strcat(linbuf, "\\- ");
236                         /*
237                          * Skip over macro names.
238                          */
239                         strcat(linbuf, &headbuf[4]);
240                 }
241         }
242         if (intro)
243                 split(linbuf, name);
244         else
245                 printf("%s\n", linbuf);
246 }
247
248 void
249 trimln(cp)
250         register char *cp;
251 {
252
253         while (*cp)
254                 cp++;
255         if (*--cp == '\n')
256                 *cp = 0;
257 }
258
259 void
260 doname(name)
261         char *name;
262 {
263         register char *dp = name, *ep;
264
265 again:
266         while (*dp && *dp != '.')
267                 putchar(*dp++);
268         if (*dp)
269                 for (ep = dp+1; *ep; ep++)
270                         if (*ep == '.') {
271                                 putchar(*dp++);
272                                 goto again;
273                         }
274         putchar('(');
275         if (*dp)
276                 dp++;
277         while (*dp)
278                 putchar (*dp++);
279         putchar(')');
280         putchar(' ');
281 }
282
283 void
284 split(line, name)
285         char *line, *name;
286 {
287         register char *cp, *dp;
288         char *sp, *sep;
289
290         cp = strchr(line, '-');
291         if (cp == 0)
292                 return;
293         sp = cp + 1;
294         for (--cp; *cp == ' ' || *cp == '\t' || *cp == '\\'; cp--)
295                 ;
296         *++cp = '\0';
297         while (*sp && (*sp == ' ' || *sp == '\t'))
298                 sp++;
299         for (sep = "", dp = line; dp && *dp; dp = cp, sep = "\n") {
300                 cp = strchr(dp, ',');
301                 if (cp) {
302                         register char *tp;
303
304                         for (tp = cp - 1; *tp == ' ' || *tp == '\t'; tp--)
305                                 ;
306                         *++tp = '\0';
307                         for (++cp; *cp == ' ' || *cp == '\t'; cp++)
308                                 ;
309                 }
310                 printf("%s%s\t", sep, dp);
311                 dorefname(name);
312                 printf("\t%s", sp);
313         }
314 }
315
316 void
317 dorefname(name)
318         char *name;
319 {
320         register char *dp = name, *ep;
321
322 again:
323         while (*dp && *dp != '.')
324                 putchar(*dp++);
325         if (*dp)
326                 for (ep = dp+1; *ep; ep++)
327                         if (*ep == '.') {
328                                 putchar(*dp++);
329                                 goto again;
330                         }
331         putchar('.');
332         if (*dp)
333                 dp++;
334         while (*dp)
335                 putchar (*dp++);
336 }
337
338 static void
339 usage()
340 {
341         (void)fprintf(stderr, "usage: getNAME [-itw] file ...\n");
342         exit(1);
343 }