=================================================================== RCS file: /cvs/mandoc/Attic/apropos_db.c,v retrieving revision 1.9 retrieving revision 1.13 diff -u -p -r1.9 -r1.13 --- mandoc/Attic/apropos_db.c 2011/11/20 15:45:37 1.9 +++ mandoc/Attic/apropos_db.c 2011/11/27 18:54:01 1.13 @@ -1,4 +1,4 @@ -/* $Id: apropos_db.c,v 1.9 2011/11/20 15:45:37 kristaps Exp $ */ +/* $Id: apropos_db.c,v 1.13 2011/11/27 18:54:01 kristaps Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons * Copyright (c) 2011 Ingo Schwarze @@ -115,17 +115,17 @@ static const struct type types[] = { }; static DB *btree_open(void); -static int btree_read(const DBT *, +static int btree_read(const DBT *, const struct mchars *, char **); static int expreval(const struct expr *, int *); -static void exprexec(const struct expr *, +static void exprexec(const struct expr *, const char *, uint64_t, struct rec *); -static int exprmark(const struct expr *, +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 *, +static int index_read(const DBT *, const DBT *, int, const struct mchars *, struct rec *); static void norm_string(const char *, const struct mchars *, char **); @@ -133,7 +133,7 @@ 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 *); + struct mchars *, int); /* * Open the keyword mandoc-db database. @@ -148,7 +148,7 @@ btree_open(void) info.flags = R_DUP; db = dbopen(MANDOC_DB, O_RDONLY, 0, DB_BTREE, &info); - if (NULL != db) + if (NULL != db) return(db); return(NULL); @@ -176,7 +176,7 @@ btree_read(const DBT *v, const struct mchars *mc, char /* * Take a Unicode codepoint and produce its UTF-8 encoding. * This isn't the best way to do this, but it works. - * The magic numbers are from the UTF-8 packaging. + * The magic numbers are from the UTF-8 packaging. * They're not as scary as they seem: read the UTF-8 spec for details. */ static size_t @@ -241,7 +241,7 @@ norm_string(const char *val, const struct mchars *mc, const char *seq, *cpp; int len, u, pos; enum mandoc_esc esc; - static const char res[] = { '\\', '\t', + static const char res[] = { '\\', '\t', ASCII_NBRSP, ASCII_HYPH, '\0' }; /* Pre-allocate by the length of the input */ @@ -287,7 +287,7 @@ norm_string(const char *val, const struct mchars *mc, if (ESCAPE_ERROR == esc) break; - /* + /* * XXX - this just does UTF-8, but we need to know * beforehand whether we should do text substitution. */ @@ -345,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; @@ -364,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); @@ -374,15 +375,14 @@ index_read(const DBT *key, const DBT *val, } /* - * Search mandocdb databases in argv (size argc) 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(int argc, char *argv[], 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 *)) { struct rectree tree; @@ -392,19 +392,24 @@ apropos_search(int argc, char *argv[], const struct op memset(&tree, 0, sizeof(struct rectree)); + rc = 0; mc = mchars_alloc(); - for (rc = 1, i = 0; rc && i < argc; i++) { - /* FIXME: ugly warning: we shouldn't get here! */ - if (chdir(argv[i])) + /* + * 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; - rc = single_search(&tree, opts, expr, terms, mc); - /* FIXME: warn and continue... ? */ + if ( ! single_search(&tree, opts, expr, terms, mc, i)) + goto out; } /* - * Count the matching files - * and feed them to the output handler. + * Count matching files, transfer to a "clean" array, then feed + * them to the output handler. */ for (mlen = i = 0; i < tree.len; i++) @@ -415,12 +420,14 @@ apropos_search(int argc, char *argv[], const struct op for (mlen = i = 0; i < tree.len; i++) if (tree.node[i].matched) - memcpy(&ress[mlen++], &tree.node[i].res, + 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]); @@ -432,7 +439,7 @@ apropos_search(int argc, char *argv[], const struct op static int single_search(struct rectree *tree, const struct opts *opts, const struct expr *expr, size_t terms, - struct mchars *mc) + struct mchars *mc, int vol) { int root, leaf, ch; uint64_t mask; @@ -453,17 +460,17 @@ single_search(struct rectree *tree, const struct opts memset(&r, 0, sizeof(struct rec)); - if (NULL == (btree = btree_open())) - return(0); + if (NULL == (btree = btree_open())) + return(1); if (NULL == (idx = index_open())) { (*btree->close)(btree); - return(0); + return(1); } while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) { - if (key.size < 2 || sizeof(struct db_val) != val.size) - break; + if (key.size < 2 || sizeof(struct db_val) != val.size) + break; if ( ! btree_read(&key, mc, &buf)) break; @@ -485,13 +492,13 @@ single_search(struct rectree *tree, const struct opts */ for (leaf = root; leaf >= 0; ) - if (rec > rs[leaf].res.rec && + if (rec > rs[leaf].res.rec && rs[leaf].rhs >= 0) leaf = rs[leaf].rhs; - else if (rec < rs[leaf].res.rec && + else if (rec < rs[leaf].res.rec && rs[leaf].lhs >= 0) leaf = rs[leaf].lhs; - else + else break; /* @@ -519,7 +526,7 @@ single_search(struct rectree *tree, const struct opts 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? */ @@ -533,10 +540,11 @@ single_search(struct rectree *tree, const struct opts (rs, (tree->len + 1) * sizeof(struct rec)); memcpy(&rs[tree->len], &r, sizeof(struct rec)); - rs[tree->len].matches = + rs[tree->len].matches = mandoc_calloc(terms, sizeof(int)); - exprexec(expr, buf, mask, &rs[tree->len]); + exprexec(expr, buf, mask, &rs[tree->len]); + /* Append to our tree. */ if (leaf >= 0) { @@ -546,11 +554,11 @@ single_search(struct rectree *tree, const struct opts rs[leaf].lhs = tree->len; } else root = tree->len; - + memset(&r, 0, sizeof(struct rec)); tree->len++; } - + (*btree->close)(btree); (*idx->close)(idx); @@ -571,7 +579,51 @@ recfree(struct rec *rec) free(rec->matches); } +/* + * Compile a list of straight-up terms. + * The arguments are re-written into ~[[:<:]]term[[:>:]], or "term" + * surrounded by word boundaries, then pumped through exprterm(). + * Terms are case-insensitive. + * This emulates whatis(1) behaviour. + */ struct expr * +termcomp(int argc, char *argv[], size_t *tt) +{ + char *buf; + int pos; + struct expr *e, *next; + size_t sz; + + buf = NULL; + e = NULL; + *tt = 0; + + for (pos = 0; pos < argc; pos++) { + sz = strlen(argv[pos]) + 16; + buf = mandoc_realloc(buf, sz); + strlcpy(buf, "~[[:<:]]", sz); + strlcat(buf, argv[pos], sz); + strlcat(buf, "[[:>:]]", sz); + if (NULL == (next = exprterm(buf, 0))) { + free(buf); + exprfree(e); + return(NULL); + } + if (NULL != e) + e->next = next; + e = next; + (*tt)++; + } + + free(buf); + return(e); +} + +/* + * Compile a sequence of logical expressions. + * See apropos.1 for a grammar of this sequence. + */ +struct expr * exprcomp(int argc, char *argv[], size_t *tt) { int pos, lvl; @@ -625,7 +677,7 @@ exprexpr(int argc, char *argv[], int *pos, int *lvl, s log = 0; if (NULL != e && 0 == strcmp("-a", argv[*pos])) - log = 1; + log = 1; else if (NULL != e && 0 == strcmp("-o", argv[*pos])) log = 2; @@ -721,7 +773,7 @@ exprterm(char *buf, int cs) e.mask = TYPE_Nm | TYPE_Nd; if (e.regex) { - i = REG_EXTENDED | REG_NOSUB | cs ? 0 : REG_ICASE; + i = REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE); if (regcomp(&e.re, e.v, i)) return(NULL); } @@ -737,7 +789,7 @@ void exprfree(struct expr *p) { struct expr *pp; - + while (NULL != p) { if (p->subexpr) exprfree(p->subexpr); @@ -751,7 +803,7 @@ exprfree(struct expr *p) } static int -exprmark(const struct expr *p, const char *cp, +exprmark(const struct expr *p, const char *cp, uint64_t mask, int *ms) { @@ -806,7 +858,7 @@ expreval(const struct expr *p, int *ms) for ( ; p->next && p->next->and; p = p->next) { /* Evaluate a subexpression, if applicable. */ if (p->next->subexpr && ! ms[p->next->index]) - ms[p->next->index] = + ms[p->next->index] = expreval(p->next->subexpr, ms); match = match && ms[p->next->index]; } @@ -823,11 +875,11 @@ expreval(const struct expr *p, int *ms) * If this evaluates to true, mark the expression as satisfied. */ static void -exprexec(const struct expr *p, const char *cp, +exprexec(const struct expr *e, const char *cp, uint64_t mask, struct rec *r) { assert(0 == r->matched); - exprmark(p, cp, mask, r->matches); - r->matched = expreval(p, r->matches); + exprmark(e, cp, mask, r->matches); + r->matched = expreval(e, r->matches); }