]> git.cameronkatri.com Git - mandoc.git/blobdiff - apropos_db.c
Update historical record to be historical and not made-up. Data from
[mandoc.git] / apropos_db.c
index c6ed8deda56b73de1cb1670f84e78be752d2ebdd..534185323739fe18695cecc3030eb7ed284a3c1a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: apropos_db.c,v 1.6 2011/11/20 12:39:08 kristaps Exp $ */
+/*     $Id: apropos_db.c,v 1.10 2011/11/20 16:29:50 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -22,6 +22,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #ifdef __linux__
 # include <db_185.h>
@@ -64,46 +65,51 @@ 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" },
-       { TYPE_At, "At" },
-       { TYPE_Bsx, "Bsx" },
-       { TYPE_Bx, "Bx" },
-       { TYPE_Cd, "Cd" },
-       { TYPE_Cm, "Cm" },
-       { TYPE_Dv, "Dv" },
-       { TYPE_Dx, "Dx" },
-       { TYPE_Em, "Em" },
-       { TYPE_Er, "Er" },
-       { TYPE_Ev, "Ev" },
-       { TYPE_Fa, "Fa" },
-       { TYPE_Fl, "Fl" },
-       { TYPE_Fn, "Fn" },
-       { TYPE_Fn, "Fo" },
-       { TYPE_Ft, "Ft" },
-       { TYPE_Fx, "Fx" },
-       { TYPE_Ic, "Ic" },
-       { TYPE_In, "In" },
-       { TYPE_Lb, "Lb" },
-       { TYPE_Li, "Li" },
-       { TYPE_Lk, "Lk" },
-       { TYPE_Ms, "Ms" },
-       { TYPE_Mt, "Mt" },
-       { TYPE_Nd, "Nd" },
-       { TYPE_Nm, "Nm" },
-       { TYPE_Nx, "Nx" },
-       { TYPE_Ox, "Ox" },
-       { TYPE_Pa, "Pa" },
-       { TYPE_Rs, "Rs" },
-       { TYPE_Sh, "Sh" },
-       { TYPE_Ss, "Ss" },
-       { TYPE_St, "St" },
-       { TYPE_Sy, "Sy" },
-       { TYPE_Tn, "Tn" },
-       { TYPE_Va, "Va" },
-       { TYPE_Va, "Vt" },
-       { TYPE_Xr, "Xr" },
+       { TYPE_An, "An" },
+       { TYPE_Ar, "Ar" },
+       { TYPE_At, "At" },
+       { TYPE_Bsx, "Bsx" },
+       { TYPE_Bx, "Bx" },
+       { TYPE_Cd, "Cd" },
+       { TYPE_Cm, "Cm" },
+       { TYPE_Dv, "Dv" },
+       { TYPE_Dx, "Dx" },
+       { TYPE_Em, "Em" },
+       { TYPE_Er, "Er" },
+       { TYPE_Ev, "Ev" },
+       { TYPE_Fa, "Fa" },
+       { TYPE_Fl, "Fl" },
+       { TYPE_Fn, "Fn" },
+       { TYPE_Fn, "Fo" },
+       { TYPE_Ft, "Ft" },
+       { TYPE_Fx, "Fx" },
+       { TYPE_Ic, "Ic" },
+       { TYPE_In, "In" },
+       { TYPE_Lb, "Lb" },
+       { TYPE_Li, "Li" },
+       { TYPE_Lk, "Lk" },
+       { TYPE_Ms, "Ms" },
+       { TYPE_Mt, "Mt" },
+       { TYPE_Nd, "Nd" },
+       { TYPE_Nm, "Nm" },
+       { TYPE_Nx, "Nx" },
+       { TYPE_Ox, "Ox" },
+       { TYPE_Pa, "Pa" },
+       { TYPE_Rs, "Rs" },
+       { TYPE_Sh, "Sh" },
+       { TYPE_Ss, "Ss" },
+       { TYPE_St, "St" },
+       { TYPE_Sy, "Sy" },
+       { TYPE_Tn, "Tn" },
+       { TYPE_Va, "Va" },
+       { TYPE_Va, "Vt" },
+       { TYPE_Xr, "Xr" },
        { INT_MAX, "any" },
        { 0, NULL }
 };
@@ -125,6 +131,9 @@ 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 *);
 
 /*
  * Open the keyword mandoc-db database.
@@ -365,46 +374,98 @@ 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))
+                       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              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) 
@@ -474,62 +535,33 @@ apropos_search(const struct opts *opts, const struct expr *expr,
                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.
-        */
-
-       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);
+       (*btree->close)(btree);
+       (*idx->close)(idx);
 
        free(buf);
-       free(rs);
-       return(rc);
+       return(1 == ch);
 }
 
 static void