=================================================================== RCS file: /cvs/mandoc/mansearch.c,v retrieving revision 1.38 retrieving revision 1.46 diff -u -p -r1.38 -r1.46 --- mandoc/mansearch.c 2014/07/12 14:00:25 1.38 +++ mandoc/mansearch.c 2014/08/21 20:29:07 1.46 @@ -1,4 +1,4 @@ -/* $Id: mansearch.c,v 1.38 2014/07/12 14:00:25 schwarze Exp $ */ +/* $Id: mansearch.c,v 1.46 2014/08/21 20:29:07 schwarze Exp $ */ /* * Copyright (c) 2012 Kristaps Dzonsons * Copyright (c) 2013, 2014 Ingo Schwarze @@ -15,11 +15,11 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include +#include + #include #include #include @@ -32,12 +32,15 @@ #include #include -#ifdef HAVE_OHASH +#if HAVE_OHASH #include #else #include "compat_ohash.h" #endif #include +#ifndef SQLITE_DETERMINISTIC +#define SQLITE_DETERMINISTIC 0 +#endif #include "mandoc.h" #include "mandoc_aux.h" @@ -94,6 +97,7 @@ 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, const char *newstr, int count); static void sql_match(sqlite3_context *context, @@ -119,7 +123,8 @@ mansearch_setup(int start) } pagecache = mmap(NULL, PC_PAGESIZE * PC_NUMPAGES, - PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANON, -1, 0); if (MAP_FAILED == pagecache) { perror("mmap"); @@ -154,7 +159,6 @@ int mansearch(const struct mansearch *search, const struct manpaths *paths, int argc, char *argv[], - const char *outkey, struct manpage **res, size_t *sz) { int fd, rc, c, indexbit; @@ -190,11 +194,11 @@ mansearch(const struct mansearch *search, goto out; outbit = 0; - if (NULL != outkey) { + if (NULL != search->outkey) { for (indexbit = 0, iterbit = 1; indexbit < mansearch_keymax; indexbit++, iterbit <<= 1) { - if (0 == strcasecmp(outkey, + if (0 == strcasecmp(search->outkey, mansearch_keynames[indexbit])) { outbit = iterbit; break; @@ -298,7 +302,7 @@ mansearch(const struct mansearch *search, mp->pageid = pageid; mp->form = sqlite3_column_int(s, 1); if (TYPE_Nd == outbit) - mp->desc = mandoc_strdup( + mp->desc = mandoc_strdup((const char *) sqlite3_column_text(s, 0)); ohash_insert(&htab, idx, mp); } @@ -331,6 +335,7 @@ mansearch(const struct mansearch *search, maxres, sizeof(struct manpage)); } mpage = *res + cur; + mpage->sec = 10; mpage->form = mp->form; buildnames(mpage, db, s, mp->pageid, paths->paths[i], mp->form); @@ -347,6 +352,7 @@ mansearch(const struct mansearch *search, sqlite3_close(db); ohash_delete(&htab); } + qsort(*res, cur, sizeof(struct manpage), manpage_compare); rc = 1; out: if (-1 != fd) { @@ -360,6 +366,31 @@ out: return(rc); } +void +mansearch_free(struct manpage *res, size_t sz) +{ + size_t i; + + for (i = 0; i < sz; i++) { + free(res[i].file); + free(res[i].names); + free(res[i].output); + } + free(res); +} + +static int +manpage_compare(const void *vp1, const void *vp2) +{ + const struct manpage *mp1, *mp2; + int diff; + + mp1 = vp1; + mp2 = vp2; + diff = mp1->sec - mp2->sec; + return(diff ? diff : strcasecmp(mp1->names, mp2->names)); +} + static void buildnames(struct manpage *mpage, sqlite3 *db, sqlite3_stmt *s, uint64_t pageid, const char *path, int form) @@ -388,10 +419,15 @@ buildnames(struct manpage *mpage, sqlite3 *db, sqlite3 /* Fetch the next name. */ - sec = sqlite3_column_text(s, 0); - arch = sqlite3_column_text(s, 1); - name = sqlite3_column_text(s, 2); + sec = (const char *)sqlite3_column_text(s, 0); + arch = (const char *)sqlite3_column_text(s, 1); + name = (const char *)sqlite3_column_text(s, 2); + /* Remember the first section found. */ + + if (9 < mpage->sec && '1' <= *sec && '9' >= *sec) + mpage->sec = (*sec - '1') + 1; + /* If the section changed, append the old one. */ if (NULL != prevsec && @@ -474,7 +510,7 @@ buildoutput(sqlite3 *db, sqlite3_stmt *s, uint64_t pag oldoutput = output; sep1 = " # "; } - data = sqlite3_column_text(s, 1); + data = (const char *)sqlite3_column_text(s, 1); mandoc_asprintf(&newoutput, "%s%s%s", oldoutput, sep1, data); free(output); @@ -715,35 +751,30 @@ exprterm(const struct mansearch *search, char *buf, in e = mandoc_calloc(1, sizeof(struct expr)); - if (MANSEARCH_MAN & search->flags) { - e->bits = search->deftype; + if (search->argmode == ARG_NAME) { + e->bits = TYPE_Nm; e->substr = buf; e->equal = 1; return(e); } /* - * Look for an '=' or '~' operator, - * unless forced to some fixed macro keys. + * Separate macro keys from search string. + * If needed, request regular expression handling + * by setting e->substr to NULL. */ - if (MANSEARCH_WHATIS & search->flags) - val = NULL; - else - val = strpbrk(buf, "=~"); - - if (NULL == val) { - e->bits = search->deftype; + if (search->argmode == ARG_WORD) { + e->bits = TYPE_Nm; + e->substr = NULL; + mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf); + cs = 0; + } else if ((val = strpbrk(buf, "=~")) == NULL) { + e->bits = TYPE_Nm | TYPE_Nd; e->substr = buf; - - /* - * Found an operator. - * Regexp search is requested by !e->substr. - */ - } else { if (val == buf) - e->bits = search->deftype; + e->bits = TYPE_Nm | TYPE_Nd; if ('=' == *val) e->substr = val + 1; *val++ = '\0'; @@ -753,15 +784,10 @@ exprterm(const struct mansearch *search, char *buf, in /* Compile regular expressions. */ - if (MANSEARCH_WHATIS & search->flags) { - e->substr = NULL; - mandoc_asprintf(&val, "[[:<:]]%s[[:>:]]", buf); - } - if (NULL == e->substr) { irc = regcomp(&e->regexp, val, REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE)); - if (MANSEARCH_WHATIS & search->flags) + if (search->argmode == ARG_WORD) free(val); if (irc) { regerror(irc, &e->regexp, errbuf, sizeof(errbuf));