summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@cvs.openbsd.org>2012-04-15 11:54:48 +0000
committerIngo Schwarze <schwarze@cvs.openbsd.org>2012-04-15 11:54:48 +0000
commit9392d89ac42d3ee81f3fbe0e2f0157d1d0ee202f (patch)
tree8af4332437af1f27e14e535475dd840f02716d25
parent72576720094b89d5d0127a875511d1df1c7e262e (diff)
Simplify by not pre-filtering the result vector for satisfied matches:
we can do this in the frontend; from kristaps@.
-rw-r--r--usr.bin/mandoc/apropos.c37
-rw-r--r--usr.bin/mandoc/apropos_db.c147
-rw-r--r--usr.bin/mandoc/apropos_db.h22
3 files changed, 104 insertions, 102 deletions
diff --git a/usr.bin/mandoc/apropos.c b/usr.bin/mandoc/apropos.c
index ef50a78e731..75159fd1438 100644
--- a/usr.bin/mandoc/apropos.c
+++ b/usr.bin/mandoc/apropos.c
@@ -1,6 +1,6 @@
-/* $Id: apropos.c,v 1.15 2012/01/05 22:07:42 schwarze Exp $ */
+/* $Id: apropos.c,v 1.16 2012/04/15 11:54:47 schwarze Exp $ */
/*
- * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,6 +15,8 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/param.h>
+
#include <assert.h>
#include <getopt.h>
#include <stdio.h>
@@ -34,8 +36,9 @@ int
apropos(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;
@@ -54,6 +57,8 @@ apropos(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 +109,17 @@ apropos(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);
}
@@ -122,16 +127,20 @@ out:
static void
list(struct res *res, size_t sz, void *arg)
{
- int i;
+ size_t i;
qsort(res, sz, sizeof(struct res), cmp);
- for (i = 0; i < (int)sz; i++)
- printf("%s(%s%s%s) - %.*s\n", res[i].title,
+ 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 : "",
- 70, res[i].desc);
+ res[i].desc);
+ }
}
static int
diff --git a/usr.bin/mandoc/apropos_db.c b/usr.bin/mandoc/apropos_db.c
index f868cd76dbd..5b47567e0b4 100644
--- a/usr.bin/mandoc/apropos_db.c
+++ b/usr.bin/mandoc/apropos_db.c
@@ -1,6 +1,6 @@
-/* $Id: apropos_db.c,v 1.17 2011/12/25 14:51:33 schwarze Exp $ */
+/* $Id: apropos_db.c,v 1.18 2012/04/15 11:54:47 schwarze Exp $ */
/*
- * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
* Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,9 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/param.h>
#include <sys/types.h>
+
#include <assert.h>
#include <fcntl.h>
#include <regex.h>
@@ -30,19 +32,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? */
@@ -61,7 +59,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 */
};
@@ -115,18 +113,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);
@@ -349,7 +346,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;
@@ -369,24 +366,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);
}
@@ -399,17 +396,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
@@ -417,39 +416,22 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
*/
for (i = 0; i < pathsz; i++) {
+ assert('/' == paths[i][0]);
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
@@ -461,8 +443,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;
@@ -473,7 +455,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);
@@ -501,10 +483,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
@@ -516,7 +498,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;
@@ -540,18 +522,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));
@@ -560,7 +542,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;
@@ -574,21 +556,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);
}
/*
@@ -879,7 +858,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/usr.bin/mandoc/apropos_db.h b/usr.bin/mandoc/apropos_db.h
index 82f5ac3d543..78cc1559318 100644
--- a/usr.bin/mandoc/apropos_db.h
+++ b/usr.bin/mandoc/apropos_db.h
@@ -1,6 +1,6 @@
-/* $Id: apropos_db.h,v 1.10 2011/12/19 02:26:33 schwarze Exp $ */
+/* $Id: apropos_db.h,v 1.11 2012/04/15 11:54:47 schwarze Exp $ */
/*
- * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -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