diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2012-04-15 11:54:48 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2012-04-15 11:54:48 +0000 |
commit | 9392d89ac42d3ee81f3fbe0e2f0157d1d0ee202f (patch) | |
tree | 8af4332437af1f27e14e535475dd840f02716d25 | |
parent | 72576720094b89d5d0127a875511d1df1c7e262e (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.c | 37 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos_db.c | 147 | ||||
-rw-r--r-- | usr.bin/mandoc/apropos_db.h | 22 |
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 |