]> git.cameronkatri.com Git - mandoc.git/blobdiff - apropos_db.c
Correctly handle constructs like
[mandoc.git] / apropos_db.c
index 98ae214f6797a137047e6539f064eeead45782a3..1c2cb4f4b3d352549c80c2db08d97ea830739e1f 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: apropos_db.c,v 1.2 2011/11/13 10:49:57 schwarze Exp $ */
+/*     $Id: apropos_db.c,v 1.4 2011/11/14 10:07:06 kristaps Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011 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
 #include "apropos_db.h"
 #include "mandoc.h"
 
-enum   match {
-       MATCH_REGEX,
-       MATCH_REGEXCASE,
-       MATCH_STR,
-       MATCH_STRCASE
-};
-
 struct expr {
-       enum match       match;
+       int              regex;
        int              mask;
        char            *v;
        regex_t          re;
@@ -71,7 +65,7 @@ static        const struct type types[] = {
 
 static DB      *btree_open(void);
 static int      btree_read(const DBT *, const struct mchars *, char **);
-static int      exprexec(const struct expr *, char *);
+static int      exprexec(const struct expr *, char *, int);
 static DB      *index_open(void);
 static int      index_read(const DBT *, const DBT *, 
                        const struct mchars *, struct rec *);
@@ -368,7 +362,7 @@ apropos_search(const struct opts *opts, const struct expr *expr,
                if ( ! btree_read(&key, mc, &buf))
                        break;
 
-               if ( ! exprexec(expr, buf))
+               if ( ! exprexec(expr, buf, *(int *)val.data))
                        continue;
 
                memcpy(&rec, val.data + 4, sizeof(recno_t));
@@ -460,55 +454,55 @@ out:
 }
 
 struct expr *
-exprcomp(int cs, char *argv[], int argc)
+exprcomp(char *buf)
 {
        struct expr     *p;
        struct expr      e;
-       int              i, pos, ch;
+       char            *key;
+       int              i, icase;
 
-       pos = 0;
-
-       if (pos > argc)
+       if ('\0' == *buf)
                return(NULL);
 
-       for (i = 0; 0 != types[i].mask; i++)
-               if (0 == strcmp(types[i].name, argv[pos]))
-                       break;
-
-       if (0 == (e.mask = types[i].mask))
-               return(NULL);
-
-       if (++pos > argc--)
-               return(NULL);
+       /*
+        * Choose regex or substring match.
+        */
 
-       if ('-' != *argv[pos]) 
-               e.match = cs ? MATCH_STRCASE : MATCH_STR;
-       else if (0 == strcmp("-eq", argv[pos]))
-               e.match = cs ? MATCH_STRCASE : MATCH_STR;
-       else if (0 == strcmp("-ieq", argv[pos]))
-               e.match = MATCH_STRCASE;
-       else if (0 == strcmp("-re", argv[pos]))
-               e.match = cs ? MATCH_REGEXCASE : MATCH_REGEX;
-       else if (0 == strcmp("-ire", argv[pos]))
-               e.match = MATCH_REGEXCASE;
-       else
-               return(NULL);
+       if (NULL == (e.v = strpbrk(buf, "=~"))) {
+               e.regex = 0;
+               e.v = buf;
+       } else {
+               e.regex = '~' == *e.v;
+               *e.v++ = '\0';
+       }
 
-       if ('-' == *argv[pos])
-               pos++;
+       /*
+        * Determine the record types to search for.
+        */
+
+       icase = 0;
+       e.mask = 0;
+       if (buf < e.v) {
+               while (NULL != (key = strsep(&buf, ","))) {
+                       if ('i' == key[0] && '\0' == key[1]) {
+                               icase = REG_ICASE;
+                               continue;
+                       }
+                       i = 0;
+                       while (types[i].mask &&
+                                       strcmp(types[i].name, key))
+                               i++;
+                       e.mask |= types[i].mask;
+               }
+       }
+       if (0 == e.mask)
+               e.mask = TYPE_Nm | TYPE_Nd;
 
-       if (pos > argc--)
+       if (e.regex &&
+           regcomp(&e.re, e.v, REG_EXTENDED | REG_NOSUB | icase))
                return(NULL);
 
-       e.v = mandoc_strdup(argv[pos]);
-
-       if (MATCH_REGEX == e.match || MATCH_REGEXCASE == e.match) {
-               ch = REG_EXTENDED | REG_NOSUB;
-               if (MATCH_REGEXCASE == e.match)
-                       ch |= REG_ICASE;
-               if (regcomp(&e.re, e.v, ch))
-                       return(NULL);
-       }
+       e.v = mandoc_strdup(e.v);
 
        p = mandoc_calloc(1, sizeof(struct expr));
        memcpy(p, &e, sizeof(struct expr));
@@ -522,7 +516,7 @@ exprfree(struct expr *p)
        if (NULL == p)
                return;
 
-       if (MATCH_REGEX == p->match)
+       if (p->regex)
                regfree(&p->re);
 
        free(p->v);
@@ -530,14 +524,14 @@ exprfree(struct expr *p)
 }
 
 static int
-exprexec(const struct expr *p, char *cp)
+exprexec(const struct expr *p, char *cp, int mask)
 {
 
-       if (MATCH_STR == p->match)
-               return(0 == strcmp(p->v, cp));
-       else if (MATCH_STRCASE == p->match)
-               return(0 == strcasecmp(p->v, cp));
+       if ( ! (mask & p->mask))
+               return(0);
 
-       assert(MATCH_REGEX == p->match);
-       return(0 == regexec(&p->re, cp, 0, NULL, 0));
+       if (p->regex)
+               return(0 == regexec(&p->re, cp, 0, NULL, 0));
+       else
+               return(NULL != strcasestr(cp, p->v));
 }