summaryrefslogtreecommitdiffstats
path: root/mansearch.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-01-20 18:21:18 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-01-20 18:21:18 +0000
commitd1726e70d7ff0b7293fb97bf3e0ed2b37cbab2ce (patch)
tree041e38837c5b93a2ef501db6b94cb4699014426b /mansearch.c
parentf118bfae6ef1e4ffdb25aff50ea427616253f6ca (diff)
downloadmandoc-d1726e70d7ff0b7293fb97bf3e0ed2b37cbab2ce.tar.gz
Make the man(1) and apropos(1) options -s and -S much less expensive:
Do not append an SQL clause looking into the large "keys" table. Instead, filter the result of the SQL query in buildnames() where equivalent data from the much smaller "mlinks" table is already available for free. This is relevant because man(1) uses the equivalent of "-S ${MACHINE}" by default since main.c rev. 1.216, to make sure that manuals for the current architecture are shown. With many ports installed, this patch can speed up man(1) by a factor of more than a hundred. Slowness reported by Theo Buehler <theo at math dot ethz dot ch>, thanks!
Diffstat (limited to 'mansearch.c')
-rw-r--r--mansearch.c70
1 files changed, 22 insertions, 48 deletions
diff --git a/mansearch.c b/mansearch.c
index 75b340bf..87664795 100644
--- a/mansearch.c
+++ b/mansearch.c
@@ -1,7 +1,7 @@
/* $Id$ */
/*
* Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -85,7 +85,8 @@ struct match {
int form; /* bit field: formatted, zipped? */
};
-static void buildnames(struct manpage *, sqlite3 *,
+static void buildnames(const struct mansearch *,
+ struct manpage *, sqlite3 *,
sqlite3_stmt *, uint64_t,
const char *, int form);
static char *buildoutput(sqlite3 *, sqlite3_stmt *,
@@ -96,8 +97,6 @@ static void *hash_calloc(size_t, size_t, void *);
static struct expr *exprcomp(const struct mansearch *,
int, char *[]);
static void exprfree(struct expr *);
-static struct expr *exprspec(struct expr *, uint64_t,
- const char *, const char *);
static struct expr *exprterm(const struct mansearch *, char *, int);
static int manpage_compare(const void *, const void *);
static void sql_append(char **sql, size_t *sz,
@@ -343,14 +342,16 @@ mansearch(const struct mansearch *search,
mpage->bits = mp->bits;
mpage->sec = 10;
mpage->form = mp->form;
- buildnames(mpage, db, s, mp->pageid,
+ buildnames(search, mpage, db, s, mp->pageid,
paths->paths[i], mp->form);
- mpage->output = TYPE_Nd & outbit ?
- mp->desc : outbit ?
- buildoutput(db, s2, mp->pageid, outbit) : NULL;
-
+ if (mpage->names != NULL) {
+ mpage->output = TYPE_Nd & outbit ?
+ mp->desc : outbit ?
+ buildoutput(db, s2, mp->pageid, outbit) :
+ NULL;
+ cur++;
+ }
free(mp);
- cur++;
}
sqlite3_finalize(s);
@@ -407,7 +408,8 @@ manpage_compare(const void *vp1, const void *vp2)
}
static void
-buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s,
+buildnames(const struct mansearch *search, struct manpage *mpage,
+ sqlite3 *db, sqlite3_stmt *s,
uint64_t pageid, const char *path, int form)
{
char *newnames, *prevsec, *prevarch;
@@ -432,10 +434,15 @@ buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s,
sep1 = ", ";
}
- /* Fetch the next name. */
+ /* Fetch the next name, rejecting sec/arch mismatches. */
sec = (const char *)sqlite3_column_text(s, 0);
+ if (search->sec != NULL && strcasecmp(sec, search->sec))
+ continue;
arch = (const char *)sqlite3_column_text(s, 1);
+ if (search->arch != NULL && *arch != '\0' &&
+ strcasecmp(arch, search->arch))
+ continue;
name = (const char *)sqlite3_column_text(s, 2);
/* Remember the first section found. */
@@ -645,8 +652,7 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
struct expr *first, *prev, *cur, *next;
first = cur = NULL;
- logic = igncase = toclose = 0;
- toopen = NULL != search->sec || NULL != search->arch;
+ logic = igncase = toopen = toclose = 0;
for (i = 0; i < argc; i++) {
if (0 == strcmp("(", argv[i])) {
@@ -712,17 +718,8 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
toopen = logic = igncase = 0;
}
- if (toopen || logic || igncase || toclose)
- goto fail;
-
- if (NULL != search->sec || NULL != search->arch)
- cur->close++;
- if (NULL != search->arch)
- cur = exprspec(cur, TYPE_arch, search->arch, "^(%s|any)$");
- if (NULL != search->sec)
- exprspec(cur, TYPE_sec, search->sec, "^%s$");
-
- return(first);
+ if ( ! (toopen || logic || igncase || toclose))
+ return(first);
fail:
if (NULL != first)
@@ -731,29 +728,6 @@ fail:
}
static struct expr *
-exprspec(struct expr *cur, uint64_t key, const char *value,
- const char *format)
-{
- char errbuf[BUFSIZ];
- char *cp;
- int irc;
-
- mandoc_asprintf(&cp, format, value);
- cur->next = mandoc_calloc(1, sizeof(struct expr));
- cur = cur->next;
- cur->and = 1;
- cur->bits = key;
- if (0 != (irc = regcomp(&cur->regexp, cp,
- REG_EXTENDED | REG_NOSUB | REG_ICASE))) {
- regerror(irc, &cur->regexp, errbuf, sizeof(errbuf));
- fprintf(stderr, "regcomp: %s\n", errbuf);
- cur->substr = value;
- }
- free(cp);
- return(cur);
-}
-
-static struct expr *
exprterm(const struct mansearch *search, char *buf, int cs)
{
char errbuf[BUFSIZ];