summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apropos.c25
-rw-r--r--apropos_db.c140
-rw-r--r--apropos_db.h18
-rw-r--r--cgi.c35
4 files changed, 114 insertions, 104 deletions
diff --git a/apropos.c b/apropos.c
index 5589cbaf..0ca307a9 100644
--- a/apropos.c
+++ b/apropos.c
@@ -18,6 +18,7 @@
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+#include <sys/param.h>
#include <assert.h>
#include <getopt.h>
@@ -39,8 +40,9 @@ int
main(int argc, char *argv[])
{
int ch, rc, whatis;
+ struct res *res;
struct manpaths paths;
- size_t terms;
+ size_t terms, ressz;
struct opts opts;
struct expr *e;
char *defpaths, *auxpaths;
@@ -59,6 +61,8 @@ main(int argc, char *argv[])
memset(&paths, 0, sizeof(struct manpaths));
memset(&opts, 0, sizeof(struct opts));
+ ressz = 0;
+ res = NULL;
auxpaths = defpaths = NULL;
conf_file = NULL;
e = NULL;
@@ -104,17 +108,17 @@ main(int argc, char *argv[])
}
rc = apropos_search
- (paths.sz, paths.paths,
- &opts, e, terms, NULL, list);
-
- if (0 == rc)
- fprintf(stderr, "%s: Error reading "
- "manual database\n", progname);
+ (paths.sz, paths.paths, &opts,
+ e, terms, NULL, &ressz, &res, list);
+ if (0 == rc) {
+ fprintf(stderr, "%s: Bad database\n", progname);
+ goto out;
+ }
out:
manpath_free(&paths);
+ resfree(res, ressz);
exprfree(e);
-
return(rc ? EXIT_SUCCESS : EXIT_FAILURE);
}
@@ -126,13 +130,16 @@ list(struct res *res, size_t sz, void *arg)
qsort(res, sz, sizeof(struct res), cmp);
- for (i = 0; i < sz; i++)
+ for (i = 0; i < sz; i++) {
+ if ( ! res[i].matched)
+ continue;
printf("%s(%s%s%s) - %.70s\n",
res[i].title,
res[i].cat,
*res[i].arch ? "/" : "",
*res[i].arch ? res[i].arch : "",
res[i].desc);
+ }
}
static int
diff --git a/apropos_db.c b/apropos_db.c
index 68eb5bba..78c2b118 100644
--- a/apropos_db.c
+++ b/apropos_db.c
@@ -42,19 +42,15 @@
#include "apropos_db.h"
#include "mandoc.h"
-struct rec {
- struct res res; /* resulting record info */
- /*
- * Maintain a binary tree for checking the uniqueness of `rec'
- * when adding elements to the results array.
- * Since the results array is dynamic, use offset in the array
- * instead of a pointer to the structure.
- */
- int lhs;
- int rhs;
- int matched; /* expression is true */
- int *matches; /* partial truth evaluations */
-};
+#define RESFREE(_x) \
+ do { \
+ free((_x)->file); \
+ free((_x)->cat); \
+ free((_x)->title); \
+ free((_x)->arch); \
+ free((_x)->desc); \
+ free((_x)->matches); \
+ } while (/*CONSTCOND*/0)
struct expr {
int regex; /* is regex? */
@@ -73,7 +69,7 @@ struct type {
};
struct rectree {
- struct rec *node; /* record array for dir tree */
+ struct res *node; /* record array for dir tree */
int len; /* length of record array */
};
@@ -127,18 +123,17 @@ static int btree_read(const DBT *, const DBT *,
uint64_t *, recno_t *, char **);
static int expreval(const struct expr *, int *);
static void exprexec(const struct expr *,
- const char *, uint64_t, struct rec *);
+ const char *, uint64_t, struct res *);
static int exprmark(const struct expr *,
const char *, uint64_t, int *);
static struct expr *exprexpr(int, char *[], int *, int *, size_t *);
static struct expr *exprterm(char *, int);
static DB *index_open(void);
static int index_read(const DBT *, const DBT *, int,
- const struct mchars *, struct rec *);
+ const struct mchars *, struct res *);
static void norm_string(const char *,
const struct mchars *, char **);
static size_t norm_utf8(unsigned int, char[7]);
-static void recfree(struct rec *);
static int single_search(struct rectree *, const struct opts *,
const struct expr *, size_t terms,
struct mchars *, int);
@@ -361,7 +356,7 @@ index_open(void)
*/
static int
index_read(const DBT *key, const DBT *val, int index,
- const struct mchars *mc, struct rec *rec)
+ const struct mchars *mc, struct res *rec)
{
size_t left;
char *np, *cp;
@@ -381,24 +376,24 @@ index_read(const DBT *key, const DBT *val, int index,
cp = val->data;
assert(sizeof(recno_t) == key->size);
- memcpy(&rec->res.rec, key->data, key->size);
- rec->res.volume = index;
+ memcpy(&rec->rec, key->data, key->size);
+ rec->volume = index;
if ('d' == (type = *cp++))
- rec->res.type = RESTYPE_MDOC;
+ rec->type = RESTYPE_MDOC;
else if ('a' == type)
- rec->res.type = RESTYPE_MAN;
+ rec->type = RESTYPE_MAN;
else if ('c' == type)
- rec->res.type = RESTYPE_CAT;
+ rec->type = RESTYPE_CAT;
else
return(0);
left--;
- INDEX_BREAD(rec->res.file);
- INDEX_BREAD(rec->res.cat);
- INDEX_BREAD(rec->res.title);
- INDEX_BREAD(rec->res.arch);
- INDEX_BREAD(rec->res.desc);
+ INDEX_BREAD(rec->file);
+ INDEX_BREAD(rec->cat);
+ INDEX_BREAD(rec->title);
+ INDEX_BREAD(rec->arch);
+ INDEX_BREAD(rec->desc);
return(1);
}
@@ -411,17 +406,19 @@ index_read(const DBT *key, const DBT *val, int index,
int
apropos_search(int pathsz, char **paths, const struct opts *opts,
const struct expr *expr, size_t terms, void *arg,
+ size_t *sz, struct res **resp,
void (*res)(struct res *, size_t, void *))
{
struct rectree tree;
struct mchars *mc;
- struct res *ress;
- int i, mlen, rc;
+ int i, rc;
memset(&tree, 0, sizeof(struct rectree));
rc = 0;
mc = mchars_alloc();
+ *sz = 0;
+ *resp = NULL;
/*
* Main loop. Change into the directory containing manpage
@@ -431,37 +428,19 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
for (i = 0; i < pathsz; i++) {
if (chdir(paths[i]))
continue;
- if ( ! single_search(&tree, opts, expr, terms, mc, i))
- goto out;
- }
-
- /*
- * Count matching files, transfer to a "clean" array, then feed
- * them to the output handler.
- */
-
- for (mlen = i = 0; i < tree.len; i++)
- if (tree.node[i].matched)
- mlen++;
-
- ress = mandoc_malloc(mlen * sizeof(struct res));
-
- for (mlen = i = 0; i < tree.len; i++)
- if (tree.node[i].matched)
- memcpy(&ress[mlen++], &tree.node[i].res,
- sizeof(struct res));
-
- (*res)(ress, mlen, arg);
- free(ress);
+ if (single_search(&tree, opts, expr, terms, mc, i))
+ continue;
- rc = 1;
-out:
- for (i = 0; i < tree.len; i++)
- recfree(&tree.node[i]);
+ resfree(tree.node, tree.len);
+ mchars_free(mc);
+ return(0);
+ }
- free(tree.node);
+ (*res)(tree.node, tree.len, arg);
+ *sz = tree.len;
+ *resp = tree.node;
mchars_free(mc);
- return(rc);
+ return(1);
}
static int
@@ -473,8 +452,8 @@ single_search(struct rectree *tree, const struct opts *opts,
DBT key, val;
DB *btree, *idx;
char *buf;
- struct rec *rs;
- struct rec r;
+ struct res *rs;
+ struct res r;
uint64_t mask;
recno_t rec;
@@ -485,7 +464,7 @@ single_search(struct rectree *tree, const struct opts *opts,
buf = NULL;
rs = tree->node;
- memset(&r, 0, sizeof(struct rec));
+ memset(&r, 0, sizeof(struct res));
if (NULL == (btree = btree_open()))
return(1);
@@ -513,10 +492,10 @@ single_search(struct rectree *tree, const struct opts *opts,
*/
for (leaf = root; leaf >= 0; )
- if (rec > rs[leaf].res.rec &&
+ if (rec > rs[leaf].rec &&
rs[leaf].rhs >= 0)
leaf = rs[leaf].rhs;
- else if (rec < rs[leaf].res.rec &&
+ else if (rec < rs[leaf].rec &&
rs[leaf].lhs >= 0)
leaf = rs[leaf].lhs;
else
@@ -528,7 +507,7 @@ single_search(struct rectree *tree, const struct opts *opts,
* try to evaluate it now and continue anyway.
*/
- if (leaf >= 0 && rs[leaf].res.rec == rec) {
+ if (leaf >= 0 && rs[leaf].rec == rec) {
if (0 == rs[leaf].matched)
exprexec(expr, buf, mask, &rs[leaf]);
continue;
@@ -552,18 +531,18 @@ single_search(struct rectree *tree, const struct opts *opts,
/* XXX: this should be elsewhere, I guess? */
- if (opts->cat && strcasecmp(opts->cat, r.res.cat))
+ if (opts->cat && strcasecmp(opts->cat, r.cat))
continue;
- if (opts->arch && *r.res.arch)
- if (strcasecmp(opts->arch, r.res.arch))
+ if (opts->arch && *r.arch)
+ if (strcasecmp(opts->arch, r.arch))
continue;
tree->node = rs = mandoc_realloc
- (rs, (tree->len + 1) * sizeof(struct rec));
+ (rs, (tree->len + 1) * sizeof(struct res));
- memcpy(&rs[tree->len], &r, sizeof(struct rec));
- memset(&r, 0, sizeof(struct rec));
+ memcpy(&rs[tree->len], &r, sizeof(struct res));
+ memset(&r, 0, sizeof(struct res));
rs[tree->len].matches =
mandoc_calloc(terms, sizeof(int));
@@ -572,7 +551,7 @@ single_search(struct rectree *tree, const struct opts *opts,
/* Append to our tree. */
if (leaf >= 0) {
- if (rec > rs[leaf].res.rec)
+ if (rec > rs[leaf].rec)
rs[leaf].rhs = tree->len;
else
rs[leaf].lhs = tree->len;
@@ -586,21 +565,18 @@ single_search(struct rectree *tree, const struct opts *opts,
(*idx->close)(idx);
free(buf);
- recfree(&r);
+ RESFREE(&r);
return(1 == ch);
}
-static void
-recfree(struct rec *rec)
+void
+resfree(struct res *rec, size_t sz)
{
+ size_t i;
- free(rec->res.file);
- free(rec->res.cat);
- free(rec->res.title);
- free(rec->res.arch);
- free(rec->res.desc);
-
- free(rec->matches);
+ for (i = 0; i < sz; i++)
+ RESFREE(&rec[i]);
+ free(rec);
}
/*
@@ -891,7 +867,7 @@ expreval(const struct expr *p, int *ms)
*/
static void
exprexec(const struct expr *e, const char *cp,
- uint64_t mask, struct rec *r)
+ uint64_t mask, struct res *r)
{
assert(0 == r->matched);
diff --git a/apropos_db.h b/apropos_db.h
index 9af530a6..31a6b780 100644
--- a/apropos_db.h
+++ b/apropos_db.h
@@ -36,6 +36,18 @@ struct res {
* searched for manual page databases.
*/
unsigned int volume;
+ /*
+ * The following fields are used internally.
+ *
+ * Maintain a binary tree for checking the uniqueness of `rec'
+ * when adding elements to the results array.
+ * Since the results array is dynamic, use offset in the array
+ * instead of a pointer to the structure.
+ */
+ int lhs;
+ int rhs;
+ int matched; /* expression is true */
+ int *matches; /* partial truth evaluations */
};
struct opts {
@@ -47,11 +59,13 @@ __BEGIN_DECLS
struct expr;
-int apropos_search(int, char **, const struct opts *,
- const struct expr *, size_t, void *,
+int apropos_search(int, char **, const struct opts *,
+ const struct expr *, size_t,
+ void *, size_t *, struct res **,
void (*)(struct res *, size_t, void *));
struct expr *exprcomp(int, char *[], size_t *);
void exprfree(struct expr *);
+void resfree(struct res *, size_t);
struct expr *termcomp(int, char *[], size_t *);
__END_DECLS
diff --git a/cgi.c b/cgi.c
index d560f41c..360ba5df 100644
--- a/cgi.c
+++ b/cgi.c
@@ -495,15 +495,22 @@ resp_baddb(void)
static void
resp_search(struct res *r, size_t sz, void *arg)
{
- int i;
+ size_t i, matched;
const struct req *req;
req = (const struct req *)arg;
if (sz > 0)
assert(req->q.manroot >= 0);
+
+ for (matched = i = 0; i < sz; i++)
+ if (r[i].matched)
+ matched++;
- if (1 == sz) {
+ if (1 == matched) {
+ for (i = 0; i < sz; i++)
+ if (r[i].matched)
+ break;
/*
* If we have just one result, then jump there now
* without any delay.
@@ -511,21 +518,19 @@ resp_search(struct res *r, size_t sz, void *arg)
puts("Status: 303 See Other");
printf("Location: http://%s%s/show/%d/%u/%u.html?",
host, progname, req->q.manroot,
- r[0].volume, r[0].rec);
+ r[i].volume, r[i].rec);
http_printquery(req);
puts("\n"
"Content-Type: text/html; charset=utf-8\n");
return;
}
- qsort(r, sz, sizeof(struct res), cmp);
-
resp_begin_html(200, NULL);
resp_searchform(req);
puts("<DIV CLASS=\"results\">");
- if (0 == sz) {
+ if (0 == matched) {
puts("<P>\n"
"No results found.\n"
"</P>\n"
@@ -534,9 +539,13 @@ resp_search(struct res *r, size_t sz, void *arg)
return;
}
+ qsort(r, sz, sizeof(struct res), cmp);
+
puts("<TABLE>");
- for (i = 0; i < (int)sz; i++) {
+ for (i = 0; i < sz; i++) {
+ if ( ! r[i].matched)
+ continue;
printf("<TR>\n"
"<TD CLASS=\"title\">\n"
"<A HREF=\"%s/show/%d/%u/%u.html?",
@@ -870,10 +879,11 @@ out:
static void
pg_search(const struct req *req, char *path)
{
- size_t tt;
+ size_t tt, ressz;
struct manpaths ps;
int i, sz, rc;
const char *ep, *start;
+ struct res *res;
char **cp;
struct opts opt;
struct expr *expr;
@@ -891,6 +901,8 @@ pg_search(const struct req *req, char *path)
rc = -1;
sz = 0;
cp = NULL;
+ ressz = 0;
+ res = NULL;
/*
* Begin by chdir()ing into the root of the manpath.
@@ -938,20 +950,21 @@ pg_search(const struct req *req, char *path)
if (NULL != expr)
rc = apropos_search
- (ps.sz, ps.paths, &opt,
- expr, tt, (void *)req, resp_search);
+ (ps.sz, ps.paths, &opt, expr, tt,
+ (void *)req, &ressz, &res, resp_search);
/* ...unless errors occured. */
if (0 == rc)
resp_baddb();
else if (-1 == rc)
- resp_search(NULL, 0, (void *)req);
+ resp_search(NULL, 0, NULL);
for (i = 0; i < sz; i++)
free(cp[i]);
free(cp);
+ resfree(res, ressz);
exprfree(expr);
manpath_free(&ps);
}