f5d1425f8615d786c662fa441dace220242740d7
[dragonfly.git] / contrib / mdocml / apropos.c
1 /*      $Id: apropos.c,v 1.27.2.1 2013/09/17 23:23:10 schwarze Exp $ */
2 /*
3  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
4  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21 #include <sys/param.h>
22
23 #include <assert.h>
24 #include <getopt.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "apropos_db.h"
30 #include "mandoc.h"
31 #include "manpath.h"
32
33 static  int      cmp(const void *, const void *);
34 static  void     list(struct res *, size_t, void *);
35
36 static  char    *progname;
37
38 int
39 main(int argc, char *argv[])
40 {
41         int              ch, rc, whatis;
42         struct res      *res;
43         struct manpaths  paths;
44         size_t           terms, ressz;
45         struct opts      opts;
46         struct expr     *e;
47         char            *defpaths, *auxpaths;
48         char            *conf_file;
49         extern char     *optarg;
50         extern int       optind;
51
52         progname = strrchr(argv[0], '/');
53         if (progname == NULL)
54                 progname = argv[0];
55         else
56                 ++progname;
57
58         whatis = (0 == strncmp(progname, "whatis", 6));
59
60         memset(&paths, 0, sizeof(struct manpaths));
61         memset(&opts, 0, sizeof(struct opts));
62
63         ressz = 0;
64         res = NULL;
65         auxpaths = defpaths = NULL;
66         conf_file = NULL;
67         e = NULL;
68
69         while (-1 != (ch = getopt(argc, argv, "C:M:m:S:s:")))
70                 switch (ch) {
71                 case ('C'):
72                         conf_file = optarg;
73                         break;
74                 case ('M'):
75                         defpaths = optarg;
76                         break;
77                 case ('m'):
78                         auxpaths = optarg;
79                         break;
80                 case ('S'):
81                         opts.arch = optarg;
82                         break;
83                 case ('s'):
84                         opts.cat = optarg;
85                         break;
86                 default:
87                         goto usage;
88                 }
89
90         argc -= optind;
91         argv += optind;
92
93         if (0 == argc)
94                 goto usage;
95
96         rc = 0;
97
98         manpath_parse(&paths, conf_file, defpaths, auxpaths);
99
100         e = whatis ? termcomp(argc, argv, &terms) :
101                      exprcomp(argc, argv, &terms);
102                 
103         if (NULL == e) {
104                 fprintf(stderr, "%s: Bad expression\n", progname);
105                 goto out;
106         }
107
108         rc = apropos_search
109                 (paths.sz, paths.paths, &opts, 
110                  e, terms, NULL, &ressz, &res, list);
111
112         if (0 == rc) {
113                 fprintf(stderr, "%s: Bad database\n", progname);
114                 goto out;
115         }
116
117 out:
118         manpath_free(&paths);
119         resfree(res, ressz);
120         exprfree(e);
121         return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
122
123 usage:
124         fprintf(stderr, "usage: %s [-C file] [-M path] [-m path] "
125                         "[-S arch] [-s section]%s ...\n", progname,
126                         whatis ? " name" : "\n               expression");
127         return(EXIT_FAILURE);
128 }
129
130 /* ARGSUSED */
131 static void
132 list(struct res *res, size_t sz, void *arg)
133 {
134         size_t           i;
135
136         qsort(res, sz, sizeof(struct res), cmp);
137
138         for (i = 0; i < sz; i++) {
139                 if ( ! res[i].matched)
140                         continue;
141                 printf("%s(%s%s%s) - %.70s\n",
142                                 res[i].title,
143                                 res[i].cat,
144                                 *res[i].arch ? "/" : "",
145                                 *res[i].arch ? res[i].arch : "",
146                                 res[i].desc);
147         }
148 }
149
150 static int
151 cmp(const void *p1, const void *p2)
152 {
153
154         return(strcasecmp(((const struct res *)p1)->title,
155                                 ((const struct res *)p2)->title));
156 }