]> git.cameronkatri.com Git - mandoc.git/blobdiff - apropos_db.c
In apropos_db.c, move all btree reading (and safety checks) into the
[mandoc.git] / apropos_db.c
index 4f1a325b3af1dc861e72761eb4af4e38d7135c87..4d9ae874601f577466a3e6d99652908080debc97 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: apropos_db.c,v 1.12 2011/11/26 22:38:11 schwarze Exp $ */
+/*     $Id: apropos_db.c,v 1.17 2011/12/01 23:46:26 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -24,6 +24,8 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <arpa/inet.h>
+
 #ifdef __linux__
 # include <db_185.h>
 #else
@@ -52,7 +54,6 @@ struct        expr {
        int              regex; /* is regex? */
        int              index; /* index in match array */
        uint64_t         mask; /* type-mask */
-       int              cs; /* is case-sensitive? */
        int              and; /* is rhs of logical AND? */
        char            *v; /* search value */
        regex_t          re; /* compiled re, if regex */
@@ -115,8 +116,9 @@ static      const struct type types[] = {
 };
 
 static DB      *btree_open(void);
-static int      btree_read(const DBT *,
-                       const struct mchars *, char **);
+static int      btree_read(const DBT *, const DBT *,
+                       const struct mchars *, 
+                       struct db_val *, char **);
 static int      expreval(const struct expr *, int *);
 static void     exprexec(const struct expr *,
                        const char *, uint64_t, struct rec *);
@@ -159,17 +161,24 @@ btree_open(void)
  * Return 0 if the database is insane, else 1.
  */
 static int
-btree_read(const DBT *v, const struct mchars *mc, char **buf)
+btree_read(const DBT *k, const DBT *v, 
+               const struct mchars *mc, 
+               struct db_val *dbv, char **buf)
 {
+       const struct db_val *vp;
 
-       /* Sanity: are we nil-terminated? */
-
-       assert(v->size > 0);
+       /* Are our sizes sane? */
+       if (k->size < 2 || sizeof(struct db_val) != v->size)
+               return(0);
 
-       if ('\0' != ((char *)v->data)[(int)v->size - 1])
+       /* Is our string nil-terminated? */
+       if ('\0' != ((const char *)k->data)[(int)k->size - 1])
                return(0);
 
-       norm_string((char *)v->data, mc, buf);
+       vp = v->data;
+       norm_string((const char *)k->data, mc, buf);
+       dbv->rec = ntohl(vp->rec);
+       dbv->mask = vp->mask;
        return(1);
 }
 
@@ -366,6 +375,7 @@ index_read(const DBT *key, const DBT *val, int index,
        rec->res.rec = *(recno_t *)key->data;
        rec->res.volume = index;
 
+       INDEX_BREAD(rec->res.type);
        INDEX_BREAD(rec->res.file);
        INDEX_BREAD(rec->res.cat);
        INDEX_BREAD(rec->res.title);
@@ -442,14 +452,12 @@ single_search(struct rectree *tree, const struct opts *opts,
                struct mchars *mc, int vol)
 {
        int              root, leaf, ch;
-       uint64_t         mask;
        DBT              key, val;
        DB              *btree, *idx;
        char            *buf;
-       recno_t          rec;
        struct rec      *rs;
        struct rec       r;
-       struct db_val   *vbuf;
+       struct db_val    vb;
 
        root    = -1;
        leaf    = -1;
@@ -469,20 +477,14 @@ single_search(struct rectree *tree, const struct opts *opts,
        }
 
        while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) {
-               if (key.size < 2 || sizeof(struct db_val) != val.size)
-                       break;
-               if ( ! btree_read(&key, mc, &buf))
+               if ( ! btree_read(&key, &val, mc, &vb, &buf))
                        break;
 
-               vbuf = val.data;
-               rec = vbuf->rec;
-               mask = vbuf->mask;
-
                /*
                 * See if this keyword record matches any of the
                 * expressions we have stored.
                 */
-               if ( ! exprmark(expr, buf, mask, NULL))
+               if ( ! exprmark(expr, buf, vb.mask, NULL))
                        continue;
 
                /*
@@ -492,10 +494,10 @@ single_search(struct rectree *tree, const struct opts *opts,
                 */
 
                for (leaf = root; leaf >= 0; )
-                       if (rec > rs[leaf].res.rec &&
+                       if (vb.rec > rs[leaf].res.rec &&
                                        rs[leaf].rhs >= 0)
                                leaf = rs[leaf].rhs;
-                       else if (rec < rs[leaf].res.rec &&
+                       else if (vb.rec < rs[leaf].res.rec &&
                                        rs[leaf].lhs >= 0)
                                leaf = rs[leaf].lhs;
                        else
@@ -507,9 +509,9 @@ 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].res.rec == vb.rec) {
                        if (0 == rs[leaf].matched)
-                               exprexec(expr, buf, mask, &rs[leaf]);
+                               exprexec(expr, buf, vb.mask, &rs[leaf]);
                        continue;
                }
 
@@ -519,7 +521,7 @@ single_search(struct rectree *tree, const struct opts *opts,
                 * database, then begin partial evaluation.
                 */
 
-               key.data = &rec;
+               key.data = &vb.rec;
                key.size = sizeof(recno_t);
 
                if (0 != (*idx->get)(idx, &key, &val, 0))
@@ -543,12 +545,12 @@ single_search(struct rectree *tree, const struct opts *opts,
                rs[tree->len].matches =
                        mandoc_calloc(terms, sizeof(int));
 
-               exprexec(expr, buf, mask, &rs[tree->len]);
+               exprexec(expr, buf, vb.mask, &rs[tree->len]);
 
                /* Append to our tree. */
 
                if (leaf >= 0) {
-                       if (rec > rs[leaf].res.rec)
+                       if (vb.rec > rs[leaf].res.rec)
                                rs[leaf].rhs = tree->len;
                        else
                                rs[leaf].lhs = tree->len;
@@ -570,6 +572,7 @@ static void
 recfree(struct rec *rec)
 {
 
+       free(rec->res.type);
        free(rec->res.file);
        free(rec->res.cat);
        free(rec->res.title);
@@ -579,6 +582,49 @@ 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 = argc - 1; pos >= 0; pos--) {
+               sz = strlen(argv[pos]) + 18;
+               buf = mandoc_realloc(buf, sz);
+               strlcpy(buf, "Nm~[[:<:]]", sz);
+               strlcat(buf, argv[pos], sz);
+               strlcat(buf, "[[:>:]]", sz);
+               if (NULL == (next = exprterm(buf, 0))) {
+                       free(buf);
+                       exprfree(e);
+                       return(NULL);
+               }
+               next->next = e;
+               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)
 {
@@ -650,7 +696,6 @@ exprexpr(int argc, char *argv[], int *pos, int *lvl, size_t *tt)
                        ++(*pos);
                        ++(*lvl);
                        next = mandoc_calloc(1, sizeof(struct expr));
-                       next->cs = 1;
                        next->subexpr = exprexpr(argc, argv, pos, lvl, tt);
                        if (NULL == next->subexpr) {
                                free(next);
@@ -701,8 +746,6 @@ exprterm(char *buf, int cs)
 
        memset(&e, 0, sizeof(struct expr));
 
-       e.cs = cs;
-
        /* Choose regex or substring match. */
 
        if (NULL == (e.v = strpbrk(buf, "=~"))) {
@@ -729,7 +772,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);
        }
@@ -774,13 +817,8 @@ exprmark(const struct expr *p, const char *cp,
                if (p->regex) {
                        if (regexec(&p->re, cp, 0, NULL, 0))
                                continue;
-               } else if (p->cs) {
-                       if (NULL == strstr(cp, p->v))
-                               continue;
-               } else {
-                       if (NULL == strcasestr(cp, p->v))
-                               continue;
-               }
+               } else if (NULL == strcasestr(cp, p->v))
+                       continue;
 
                if (NULL == ms)
                        return(1);