Reimplement apropos -s NUM -S ARCH EXPR by internally converting it to
authorschwarze <schwarze@openbsd.org>
Sun, 5 Jan 2014 03:06:36 +0000 (03:06 +0000)
committerschwarze <schwarze@openbsd.org>
Sun, 5 Jan 2014 03:06:36 +0000 (03:06 +0000)
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
Before this commit, they don't, neither for the
old makewhatis(8)/apropos(1) combo nor for the new one.

While here, print error messages about invalid regexps to stderr.

usr.bin/mandoc/mandocdb.c
usr.bin/mandoc/mansearch.c

index 5837be9..9961e3a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandocdb.c,v 1.54 2014/01/05 00:29:49 schwarze Exp $ */
+/*     $Id: mandocdb.c,v 1.55 2014/01/05 03:06:36 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -1017,14 +1017,16 @@ mpages_merge(struct mchars *mc, struct mparse *mp, int check_reachable)
                            mandoc_strdup(mpage->mlinks->name);
                }
                putkey(mpage, mpage->sec, TYPE_sec);
-               putkey(mpage, mpage->arch, TYPE_arch);
+               putkey(mpage, '\0' == *mpage->arch ?
+                   "any" : mpage->arch, TYPE_arch);
 
                for (mlink = mpage->mlinks; mlink; mlink = mlink->next) {
                        if ('\0' != *mlink->dsec)
                                putkey(mpage, mlink->dsec, TYPE_sec);
                        if ('\0' != *mlink->fsec)
                                putkey(mpage, mlink->fsec, TYPE_sec);
-                       putkey(mpage, mlink->arch, TYPE_arch);
+                       putkey(mpage, '\0' == *mlink->arch ?
+                           "any" : mlink->arch, TYPE_arch);
                        putkey(mpage, mlink->name, TYPE_Nm);
                }
 
index e6cb010..16fe73f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mansearch.c,v 1.5 2014/01/05 00:29:49 schwarze Exp $ */
+/*     $Id: mansearch.c,v 1.6 2014/01/05 03:06:36 schwarze Exp $ */
 /*
  * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org>
@@ -127,6 +127,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);
@@ -134,8 +136,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,
@@ -203,7 +204,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
@@ -250,11 +251,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);
@@ -472,7 +468,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;
@@ -481,12 +477,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);
@@ -503,7 +493,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);
 }
@@ -520,7 +509,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])) {
@@ -564,20 +554,58 @@ 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);
        return(NULL);
 }
 
+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);
@@ -606,8 +634,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);
                }