* mdocml: Simplify by not pre-filtering the result vector for satisfied
@ 2012-03-24 0:31 kristaps
0 siblings, 0 replies; only message in thread
From: kristaps @ 2012-03-24 0:31 UTC (permalink / raw)
To: source
Log Message:
-----------
Simplify by not pre-filtering the result vector for satisfied matches:
we can do this in the frontend.
Modified Files:
--------------
mdocml:
apropos.c
apropos_db.c
cgi.c
apropos_db.h
Revision Data
-------------
Index: apropos_db.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos_db.c,v
retrieving revision 1.29
retrieving revision 1.30
diff -Lapropos_db.c -Lapropos_db.c -u -p -r1.29 -r1.30
--- apropos_db.c
+++ apropos_db.c
@@ -42,19 +42,15 @@
#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 *, cons
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 *va
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 *va
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,
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.
- */
+ if (single_search(&tree, opts, expr, terms, mc, i))
+ continue;
- 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]);
+ 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, cons
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, cons
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, cons
*/
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, cons
* 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, cons
/* 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, cons
/* 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, cons
(*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: apropos_db.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos_db.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -Lapropos_db.h -Lapropos_db.h -u -p -r1.11 -r1.12
--- apropos_db.h
+++ apropos_db.h
@@ -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
Index: cgi.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/cgi.c,v
retrieving revision 1.40
retrieving revision 1.41
diff -Lcgi.c -Lcgi.c -u -p -r1.40 -r1.41
--- cgi.c
+++ cgi.c
@@ -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, vo
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, vo
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 *p
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 *p
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);
}
Index: apropos.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -Lapropos.c -Lapropos.c -u -p -r1.26 -r1.27
--- apropos.c
+++ apropos.c
@@ -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 *a
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
--
To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2012-03-24 0:31 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-24 0:31 mdocml: Simplify by not pre-filtering the result vector for satisfied kristaps
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).