summaryrefslogtreecommitdiffstats
path: root/mansearch.c
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2014-01-05 03:06:43 +0000
committerIngo Schwarze <schwarze@openbsd.org>2014-01-05 03:06:43 +0000
commit309ba0ab0e453acde16dc583e036874dbeb4a2a4 (patch)
tree0067eec7fed86caa37a21ad837513356c1ac5d68 /mansearch.c
parent54a35af24eafe969f6b7acd3eb923ffa75bfb0ab (diff)
downloadmandoc-309ba0ab0e453acde16dc583e036874dbeb4a2a4.tar.gz
Reimplement apropos -s NUM -S ARCH EXPR by internally converting it to
apropos \( EXPR \) -a 'sec~^NUM$' -a 'arch~^(ARCH|any)$' in preparation for removal of sec and arch from the mpage table. Almost no functional change except for the following bonus: This also makes sure that for cross-section and cross-arch MLINKs, all of the following work: apropos -s 1 encrypt apropos -s 8 encrypt apropos -s 1 makekey apropos -s 8 makekey While here, print error messages about invalid regexps to stderr.
Diffstat (limited to 'mansearch.c')
-rw-r--r--mansearch.c72
1 files changed, 51 insertions, 21 deletions
diff --git a/mansearch.c b/mansearch.c
index 6db43e4e..a9c7a2d4 100644
--- a/mansearch.c
+++ b/mansearch.c
@@ -135,6 +135,8 @@ static void *hash_halloc(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 void sql_append(char **sql, size_t *sz,
const char *newstr, int count);
@@ -142,8 +144,7 @@ static void sql_match(sqlite3_context *context,
int argc, sqlite3_value **argv);
static void sql_regexp(sqlite3_context *context,
int argc, sqlite3_value **argv);
-static char *sql_statement(const struct expr *,
- const char *, const char *);
+static char *sql_statement(const struct expr *);
int
mansearch(const struct mansearch *search,
@@ -211,7 +212,7 @@ mansearch(const struct mansearch *search,
goto out;
}
- sql = sql_statement(e, search->arch, search->sec);
+ sql = sql_statement(e);
/*
* Loop over the directories (containing databases) for us to
@@ -258,11 +259,6 @@ mansearch(const struct mansearch *search,
if (SQLITE_OK != c)
fprintf(stderr, "%s\n", sqlite3_errmsg(db));
- if (NULL != search->arch)
- SQL_BIND_TEXT(db, s, j, search->arch);
- if (NULL != search->sec)
- SQL_BIND_TEXT(db, s, j, search->sec);
-
for (ep = e; NULL != ep; ep = ep->next) {
if (NULL == ep->substr) {
SQL_BIND_BLOB(db, s, j, ep->regexp);
@@ -480,7 +476,7 @@ sql_append(char **sql, size_t *sz, const char *newstr, int count)
* Prepare the search SQL statement.
*/
static char *
-sql_statement(const struct expr *e, const char *arch, const char *sec)
+sql_statement(const struct expr *e)
{
char *sql;
size_t sz;
@@ -489,12 +485,6 @@ sql_statement(const struct expr *e, const char *arch, const char *sec)
sql = mandoc_strdup("SELECT * FROM mpages WHERE ");
sz = strlen(sql);
- if (NULL != arch)
- sql_append(&sql, &sz, "arch = ? AND ", 1);
- if (NULL != sec)
- sql_append(&sql, &sz, "sec = ? AND ", 1);
- sql_append(&sql, &sz, "(", 1);
-
for (needop = 0; NULL != e; e = e->next) {
if (e->and)
sql_append(&sql, &sz, " AND ", 1);
@@ -511,7 +501,6 @@ sql_statement(const struct expr *e, const char *arch, const char *sec)
sql_append(&sql, &sz, ")", e->close);
needop = 1;
}
- sql_append(&sql, &sz, ")", 1);
return(sql);
}
@@ -528,7 +517,8 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
struct expr *first, *next, *cur;
first = cur = NULL;
- toopen = logic = igncase = toclose = 0;
+ logic = igncase = toclose = 0;
+ toopen = 1;
for (i = 0; i < argc; i++) {
if (0 == strcmp("(", argv[i])) {
@@ -572,8 +562,15 @@ exprcomp(const struct mansearch *search, int argc, char *argv[])
cur = first = next;
toopen = logic = igncase = 0;
}
- if ( ! (toopen || logic || igncase || toclose))
- return(first);
+ if (toopen || logic || igncase || toclose)
+ goto fail;
+
+ cur->close++;
+ cur = exprspec(cur, TYPE_arch, search->arch, "^(%s|any)$");
+ exprspec(cur, TYPE_sec, search->sec, "^%s$");
+
+ return(first);
+
fail:
if (NULL != first)
exprfree(first);
@@ -581,11 +578,42 @@ fail:
}
static struct expr *
+exprspec(struct expr *cur, uint64_t key, const char *value,
+ const char *format)
+{
+ char errbuf[BUFSIZ];
+ char *cp;
+ int irc;
+
+ if (NULL == value)
+ return(cur);
+
+ if (-1 == asprintf(&cp, format, value)) {
+ perror(0);
+ exit((int)MANDOCLEVEL_SYSERR);
+ }
+ 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];
struct expr *e;
char *key, *v;
size_t i;
+ int irc;
if ('\0' == *buf)
return(NULL);
@@ -614,8 +642,10 @@ exprterm(const struct mansearch *search, char *buf, int cs)
e->bits = search->deftype;
if ('~' == *v++) {
- if (regcomp(&e->regexp, v,
- REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE))) {
+ if (0 != (irc = regcomp(&e->regexp, v,
+ REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE)))) {
+ regerror(irc, &e->regexp, errbuf, sizeof(errbuf));
+ fprintf(stderr, "regcomp: %s\n", errbuf);
free(e);
return(NULL);
}