]> git.cameronkatri.com Git - mandoc.git/blob - apropos.c
Correctly handle constructs like
[mandoc.git] / apropos.c
1 /* $Id: apropos.c,v 1.13 2011/11/14 10:07:06 kristaps Exp $ */
2 /*
3 * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include <assert.h>
22 #include <getopt.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "apropos_db.h"
29 #include "mandoc.h"
30
31 static int cmp(const void *, const void *);
32 static void list(struct rec *, size_t, void *);
33 static void usage(void);
34
35 static char *progname;
36
37 int
38 main(int argc, char *argv[])
39 {
40 int ch;
41 size_t sz;
42 char *buf;
43 struct opts opts;
44 struct expr *e;
45 extern int optind;
46 extern char *optarg;
47
48 memset(&opts, 0, sizeof(struct opts));
49
50 progname = strrchr(argv[0], '/');
51 if (progname == NULL)
52 progname = argv[0];
53 else
54 ++progname;
55
56 while (-1 != (ch = getopt(argc, argv, "S:s:")))
57 switch (ch) {
58 case ('S'):
59 opts.arch = optarg;
60 break;
61 case ('s'):
62 opts.cat = optarg;
63 break;
64 default:
65 usage();
66 return(EXIT_FAILURE);
67 }
68
69 argc -= optind;
70 argv += optind;
71
72 if (0 == argc)
73 return(EXIT_SUCCESS);
74
75 /*
76 * Collapse expressions into a single string.
77 * First count up the contained strings, adding a space at the
78 * end of each (plus nil-terminator). Then merge.
79 */
80
81 for (sz = 0, ch = 0; ch < argc; ch++)
82 sz += strlen(argv[ch]) + 1;
83
84 buf = mandoc_malloc(++sz);
85
86 for (*buf = '\0', ch = 0; ch < argc; ch++) {
87 strlcat(buf, argv[ch], sz);
88 strlcat(buf, " ", sz);
89 }
90
91 buf[sz - 2] = '\0';
92
93 if (NULL == (e = exprcomp(buf))) {
94 fprintf(stderr, "Bad expression\n");
95 free(buf);
96 return(EXIT_FAILURE);
97 }
98
99 free(buf);
100
101 /*
102 * Configure databases.
103 * The keyword database is a btree that allows for duplicate
104 * entries.
105 * The index database is a recno.
106 */
107
108 apropos_search(&opts, e, NULL, list);
109 exprfree(e);
110 return(EXIT_SUCCESS);
111 }
112
113 /* ARGSUSED */
114 static void
115 list(struct rec *res, size_t sz, void *arg)
116 {
117 int i;
118
119 qsort(res, sz, sizeof(struct rec), cmp);
120
121 for (i = 0; i < (int)sz; i++)
122 printf("%s(%s%s%s) - %s\n", res[i].title,
123 res[i].cat,
124 *res[i].arch ? "/" : "",
125 *res[i].arch ? res[i].arch : "",
126 res[i].desc);
127 }
128
129 static int
130 cmp(const void *p1, const void *p2)
131 {
132
133 return(strcmp(((const struct rec *)p1)->title,
134 ((const struct rec *)p2)->title));
135 }
136
137 static void
138 usage(void)
139 {
140
141 fprintf(stderr, "usage: %s "
142 "[-I] "
143 "[-S arch] "
144 "[-s section] "
145 "EXPR\n",
146 progname);
147 }