=================================================================== RCS file: /cvs/mandoc/Attic/apropos_db.c,v retrieving revision 1.7 retrieving revision 1.11 diff -u -p -r1.7 -r1.11 --- mandoc/Attic/apropos_db.c 2011/11/20 12:46:53 1.7 +++ mandoc/Attic/apropos_db.c 2011/11/23 09:55:28 1.11 @@ -1,4 +1,4 @@ -/* $Id: apropos_db.c,v 1.7 2011/11/20 12:46:53 kristaps Exp $ */ +/* $Id: apropos_db.c,v 1.11 2011/11/23 09:55:28 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef __linux__ # include @@ -64,6 +65,11 @@ struct type { const char *name; }; +struct rectree { + struct rec *node; /* record array for dir tree */ + int len; /* length of record array */ +}; + static const struct type types[] = { { TYPE_An, "An" }, { TYPE_Ar, "Ar" }, @@ -119,12 +125,15 @@ static int exprmark(const struct expr *, 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 *, +static int index_read(const DBT *, const DBT *, int, const struct mchars *, struct rec *); 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); /* * Open the keyword mandoc-db database. @@ -336,7 +345,7 @@ index_open(void) * Returns 1 if an entry was unpacked, 0 if the database is insane. */ static int -index_read(const DBT *key, const DBT *val, +index_read(const DBT *key, const DBT *val, int index, const struct mchars *mc, struct rec *rec) { size_t left; @@ -355,6 +364,7 @@ index_read(const DBT *key, const DBT *val, cp = (char *)val->data; rec->res.rec = *(recno_t *)key->data; + rec->res.volume = index; INDEX_BREAD(rec->res.file); INDEX_BREAD(rec->res.cat); @@ -365,47 +375,99 @@ index_read(const DBT *key, const DBT *val, } /* - * Search the mandocdb database for the expression "expr". + * Search mandocdb databases in paths for expression "expr". * Filter out by "opts". * Call "res" with the results, which may be zero. * Return 0 if there was a database error, else return 1. */ int -apropos_search(const struct opts *opts, const struct expr *expr, - size_t terms, void *arg, +apropos_search(int pathsz, char **paths, const struct opts *opts, + const struct expr *expr, size_t terms, void *arg, void (*res)(struct res *, size_t, void *)) { - int i, rsz, root, leaf, mlen, rc, ch; + struct rectree tree; + struct mchars *mc; + struct res *ress; + int i, mlen, rc; + + memset(&tree, 0, sizeof(struct rectree)); + + rc = 0; + mc = mchars_alloc(); + + /* + * Main loop. Change into the directory containing manpage + * databases. Run our expession over each database in the set. + */ + + 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); + + rc = 1; +out: + for (i = 0; i < tree.len; i++) + recfree(&tree.node[i]); + + free(tree.node); + mchars_free(mc); + return(rc); +} + +static int +single_search(struct rectree *tree, const struct opts *opts, + const struct expr *expr, size_t terms, + struct mchars *mc, int vol) +{ + int root, leaf, ch; uint64_t mask; DBT key, val; DB *btree, *idx; - struct mchars *mc; char *buf; recno_t rec; struct rec *rs; - struct res *ress; struct rec r; struct db_val *vbuf; - rc = 0; root = -1; leaf = -1; btree = NULL; idx = NULL; - mc = NULL; buf = NULL; - rs = NULL; - rsz = 0; + rs = tree->node; memset(&r, 0, sizeof(struct rec)); - mc = mchars_alloc(); - if (NULL == (btree = btree_open())) - goto out; - if (NULL == (idx = index_open())) - goto out; + return(1); + if (NULL == (idx = index_open())) { + (*btree->close)(btree); + return(1); + } + while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) { if (key.size < 2 || sizeof(struct db_val) != val.size) break; @@ -464,7 +526,7 @@ apropos_search(const struct opts *opts, const struct e break; r.lhs = r.rhs = -1; - if ( ! index_read(&key, &val, mc, &r)) + if ( ! index_read(&key, &val, vol, mc, &r)) break; /* XXX: this should be elsewhere, I guess? */ @@ -474,62 +536,33 @@ apropos_search(const struct opts *opts, const struct e if (opts->arch && strcasecmp(opts->arch, r.res.arch)) continue; - rs = mandoc_realloc - (rs, (rsz + 1) * sizeof(struct rec)); + tree->node = rs = mandoc_realloc + (rs, (tree->len + 1) * sizeof(struct rec)); - memcpy(&rs[rsz], &r, sizeof(struct rec)); - rs[rsz].matches = mandoc_calloc(terms, sizeof(int)); + memcpy(&rs[tree->len], &r, sizeof(struct rec)); + rs[tree->len].matches = + mandoc_calloc(terms, sizeof(int)); - exprexec(expr, buf, mask, &rs[rsz]); + exprexec(expr, buf, mask, &rs[tree->len]); /* Append to our tree. */ if (leaf >= 0) { if (rec > rs[leaf].res.rec) - rs[leaf].rhs = rsz; + rs[leaf].rhs = tree->len; else - rs[leaf].lhs = rsz; + rs[leaf].lhs = tree->len; } else - root = rsz; + root = tree->len; memset(&r, 0, sizeof(struct rec)); - rsz++; + tree->len++; } - /* - * If we haven't encountered any database errors, then construct - * an array of results and push them to the caller. - */ + (*btree->close)(btree); + (*idx->close)(idx); - if (1 == ch) { - for (mlen = i = 0; i < rsz; i++) - if (rs[i].matched) - mlen++; - ress = mandoc_malloc(mlen * sizeof(struct res)); - for (mlen = i = 0; i < rsz; i++) - if (rs[i].matched) - memcpy(&ress[mlen++], &rs[i].res, - sizeof(struct res)); - (*res)(ress, mlen, arg); - free(ress); - rc = 1; - } - -out: - for (i = 0; i < rsz; i++) - recfree(&rs[i]); - - recfree(&r); - - if (mc) - mchars_free(mc); - if (btree) - (*btree->close)(btree); - if (idx) - (*idx->close)(idx); - free(buf); - free(rs); - return(rc); + return(1 == ch); } static void