=================================================================== RCS file: /cvs/mandoc/mansearch.c,v retrieving revision 1.35 retrieving revision 1.38 diff -u -p -r1.35 -r1.38 --- mandoc/mansearch.c 2014/04/23 16:34:50 1.35 +++ mandoc/mansearch.c 2014/07/12 14:00:25 1.38 @@ -1,4 +1,4 @@ -/* $Id: mansearch.c,v 1.35 2014/04/23 16:34:50 schwarze Exp $ */ +/* $Id: mansearch.c,v 1.38 2014/07/12 14:00:25 schwarze Exp $ */ /* * Copyright (c) 2012 Kristaps Dzonsons * Copyright (c) 2013, 2014 Ingo Schwarze @@ -64,13 +64,14 @@ extern const char *const mansearch_keynames[]; } while (0) struct expr { - uint64_t bits; /* type-mask */ - const char *substr; /* to search for, if applicable */ regex_t regexp; /* compiled regexp, if applicable */ + const char *substr; /* to search for, if applicable */ + struct expr *next; /* next in sequence */ + uint64_t bits; /* type-mask */ + int equal; /* equality, not subsring match */ int open; /* opening parentheses before */ int and; /* logical AND before */ int close; /* closing parentheses after */ - struct expr *next; /* next in sequence */ }; struct match { @@ -85,8 +86,8 @@ static void buildnames(struct manpage *, sqlite3 *, static char *buildoutput(sqlite3 *, sqlite3_stmt *, uint64_t, uint64_t); static void *hash_alloc(size_t, void *); -static void hash_free(void *, size_t, void *); -static void *hash_halloc(size_t, void *); +static void hash_free(void *, void *); +static void *hash_calloc(size_t, size_t, void *); static struct expr *exprcomp(const struct mansearch *, int, char *[]); static void exprfree(struct expr *); @@ -171,11 +172,9 @@ mansearch(const struct mansearch *search, unsigned int idx; size_t i, j, cur, maxres; - memset(&info, 0, sizeof(struct ohash_info)); - - info.halloc = hash_halloc; + info.calloc = hash_calloc; info.alloc = hash_alloc; - info.hfree = hash_free; + info.free = hash_free; info.key_offset = offsetof(struct match, pageid); *sz = cur = maxres = 0; @@ -328,8 +327,8 @@ mansearch(const struct mansearch *search, mp = ohash_next(&htab, &idx)) { if (cur + 1 > maxres) { maxres += 1024; - *res = mandoc_realloc(*res, - maxres * sizeof(struct manpage)); + *res = mandoc_reallocarray(*res, + maxres, sizeof(struct manpage)); } mpage = *res + cur; mpage->form = mp->form; @@ -563,6 +562,9 @@ sql_statement(const struct expr *e) ? (NULL == e->substr ? "pageid IN (SELECT pageid FROM names " "WHERE name REGEXP ?)" + : e->equal + ? "pageid IN (SELECT pageid FROM names " + "WHERE name = ?)" : "pageid IN (SELECT pageid FROM names " "WHERE name MATCH ?)") : (NULL == e->substr @@ -704,7 +706,7 @@ exprterm(const struct mansearch *search, char *buf, in { char errbuf[BUFSIZ]; struct expr *e; - char *key, *v; + char *key, *val; uint64_t iterbit; int i, irc; @@ -713,41 +715,65 @@ exprterm(const struct mansearch *search, char *buf, in e = mandoc_calloc(1, sizeof(struct expr)); - /*"whatis" mode uses an opaque string and default fields. */ - - if (MANSEARCH_WHATIS & search->flags) { - e->substr = buf; + if (MANSEARCH_MAN & search->flags) { e->bits = search->deftype; + e->substr = buf; + e->equal = 1; return(e); } /* - * If no =~ is specified, search with equality over names and - * descriptions. - * If =~ begins the phrase, use name and description fields. + * Look for an '=' or '~' operator, + * unless forced to some fixed macro keys. */ - if (NULL == (v = strpbrk(buf, "=~"))) { - e->substr = buf; + if (MANSEARCH_WHATIS & search->flags) + val = NULL; + else + val = strpbrk(buf, "=~"); + + if (NULL == val) { e->bits = search->deftype; - return(e); - } else if (v == buf) - e->bits = search->deftype; + e->substr = buf; - if ('~' == *v++) { + /* + * Found an operator. + * Regexp search is requested by !e->substr. + */ + + } else { + if (val == buf) + e->bits = search->deftype; + if ('=' == *val) + e->substr = val + 1; + *val++ = '\0'; if (NULL != strstr(buf, "arch")) cs = 0; - if (0 != (irc = regcomp(&e->regexp, v, - REG_EXTENDED | REG_NOSUB | (cs ? 0 : REG_ICASE)))) { + } + + /* 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) + free(val); + if (irc) { regerror(irc, &e->regexp, errbuf, sizeof(errbuf)); fprintf(stderr, "regcomp: %s\n", errbuf); free(e); return(NULL); } - } else - e->substr = v; - v[-1] = '\0'; + } + if (e->bits) + return(e); + /* * Parse out all possible fields. * If the field doesn't resolve, bail. @@ -790,10 +816,10 @@ exprfree(struct expr *p) } static void * -hash_halloc(size_t sz, void *arg) +hash_calloc(size_t nmemb, size_t sz, void *arg) { - return(mandoc_calloc(sz, 1)); + return(mandoc_calloc(nmemb, sz)); } static void * @@ -804,7 +830,7 @@ hash_alloc(size_t sz, void *arg) } static void -hash_free(void *p, size_t sz, void *arg) +hash_free(void *p, void *arg) { free(p);