]> git.cameronkatri.com Git - mandoc.git/commitdiff
Simplify by not pre-filtering the result vector for satisfied matches:
authorKristaps Dzonsons <kristaps@bsd.lv>
Sat, 24 Mar 2012 00:31:55 +0000 (00:31 +0000)
committerKristaps Dzonsons <kristaps@bsd.lv>
Sat, 24 Mar 2012 00:31:55 +0000 (00:31 +0000)
we can do this in the frontend.

apropos.c
apropos_db.c
apropos_db.h
cgi.c

index f222f3562033c4d0ede5ba5a54d56f97576f4509..5278832e8d1cdcef14db4801141ebf76f31a4809 100644 (file)
--- a/apropos.c
+++ b/apropos.c
@@ -1,4 +1,4 @@
-/*     $Id: apropos.c,v 1.26 2012/03/23 02:52:33 kristaps Exp $ */
+/*     $Id: apropos.c,v 1.27 2012/03/24 00:31:55 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -18,6 +18,7 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+#include <sys/param.h>
 
 #include <assert.h>
 #include <getopt.h>
@@ -39,8 +40,9 @@ int
 main(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;
@@ -59,6 +61,8 @@ main(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 +108,17 @@ main(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);
 }
 
@@ -126,13 +130,16 @@ list(struct res *res, size_t sz, void *arg)
 
        qsort(res, sz, sizeof(struct res), cmp);
 
-       for (i = 0; i < sz; i++)
+       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 : "",
                                res[i].desc);
+       }
 }
 
 static int
index 51c32b67b70bf330bc2e2fea359e922394d7a0d3..50a84230958a06816e3cfd966cb2fa35e3f758f6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: apropos_db.c,v 1.29 2012/03/23 05:07:35 kristaps Exp $ */
+/*     $Id: apropos_db.c,v 1.30 2012/03/24 00:31:55 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 #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? */
@@ -73,7 +69,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 */
 };
 
@@ -127,18 +123,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);
@@ -361,7 +356,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;
@@ -381,24 +376,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);
 }
 
@@ -411,17 +406,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
@@ -431,37 +428,19 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
        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);
+               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
@@ -473,8 +452,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;
 
@@ -485,7 +464,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);
@@ -513,10 +492,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
@@ -528,7 +507,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;
@@ -552,18 +531,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));
 
@@ -572,7 +551,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;
@@ -586,21 +565,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);
 }
 
 /*
@@ -891,7 +867,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);
index 2af91206f969609796a716fb9ea5a34670bd148e..bf0913e8d330717d6da2b2329f79f38c934838cd 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: apropos_db.h,v 1.11 2011/12/16 12:06:35 kristaps Exp $ */
+/*     $Id: apropos_db.h,v 1.12 2012/03/24 00:31:55 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -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
diff --git a/cgi.c b/cgi.c
index 4432d6b44b24ef595362acb2dcc27a5b50b763fd..205235a24c5491d771aaf9721094ee45cdd218d1 100644 (file)
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/*     $Id: cgi.c,v 1.40 2012/03/23 09:03:07 kristaps Exp $ */
+/*     $Id: cgi.c,v 1.41 2012/03/24 00:31:55 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -495,15 +495,22 @@ resp_baddb(void)
 static void
 resp_search(struct res *r, size_t sz, void *arg)
 {
-       int               i;
+       size_t           i, matched;
        const struct req *req;
 
        req = (const struct req *)arg;
 
        if (sz > 0)
                assert(req->q.manroot >= 0);
+
+       for (matched = i = 0; i < sz; i++)
+               if (r[i].matched)
+                       matched++;
        
-       if (1 == sz) {
+       if (1 == matched) {
+               for (i = 0; i < sz; i++)
+                       if (r[i].matched)
+                               break;
                /*
                 * If we have just one result, then jump there now
                 * without any delay.
@@ -511,21 +518,19 @@ resp_search(struct res *r, size_t sz, void *arg)
                puts("Status: 303 See Other");
                printf("Location: http://%s%s/show/%d/%u/%u.html?",
                                host, progname, req->q.manroot,
-                               r[0].volume, r[0].rec);
+                               r[i].volume, r[i].rec);
                http_printquery(req);
                puts("\n"
                     "Content-Type: text/html; charset=utf-8\n");
                return;
        }
 
-       qsort(r, sz, sizeof(struct res), cmp);
-
        resp_begin_html(200, NULL);
        resp_searchform(req);
 
        puts("<DIV CLASS=\"results\">");
 
-       if (0 == sz) {
+       if (0 == matched) {
                puts("<P>\n"
                     "No results found.\n"
                     "</P>\n"
@@ -534,9 +539,13 @@ resp_search(struct res *r, size_t sz, void *arg)
                return;
        }
 
+       qsort(r, sz, sizeof(struct res), cmp);
+
        puts("<TABLE>");
 
-       for (i = 0; i < (int)sz; i++) {
+       for (i = 0; i < sz; i++) {
+               if ( ! r[i].matched)
+                       continue;
                printf("<TR>\n"
                       "<TD CLASS=\"title\">\n"
                       "<A HREF=\"%s/show/%d/%u/%u.html?", 
@@ -870,10 +879,11 @@ out:
 static void
 pg_search(const struct req *req, char *path)
 {
-       size_t            tt;
+       size_t            tt, ressz;
        struct manpaths   ps;
        int               i, sz, rc;
        const char       *ep, *start;
+       struct res      *res;
        char            **cp;
        struct opts       opt;
        struct expr      *expr;
@@ -891,6 +901,8 @@ pg_search(const struct req *req, char *path)
        rc       = -1;
        sz       = 0;
        cp       = NULL;
+       ressz    = 0;
+       res      = NULL;
 
        /*
         * Begin by chdir()ing into the root of the manpath.
@@ -938,20 +950,21 @@ pg_search(const struct req *req, char *path)
 
        if (NULL != expr)
                rc = apropos_search
-                       (ps.sz, ps.paths, &opt,
-                        expr, tt, (void *)req, resp_search);
+                       (ps.sz, ps.paths, &opt, expr, tt, 
+                        (void *)req, &ressz, &res, resp_search);
 
        /* ...unless errors occured. */
 
        if (0 == rc)
                resp_baddb();
        else if (-1 == rc)
-               resp_search(NULL, 0, (void *)req);
+               resp_search(NULL, 0, NULL);
 
        for (i = 0; i < sz; i++)
                free(cp[i]);
 
        free(cp);
+       resfree(res, ressz);
        exprfree(expr);
        manpath_free(&ps);
 }