-/* $Id: apropos_db.c,v 1.1 2011/11/13 10:12:05 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 <db.h>
#endif
+#include "mandocdb.h"
#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;
};
static const struct type types[] = {
- { TYPE_NAME, "name" },
- { TYPE_FUNCTION, "func" },
- { TYPE_UTILITY, "utility" },
- { TYPE_INCLUDES, "incl" },
- { TYPE_VARIABLE, "var" },
- { TYPE_STANDARD, "stand" },
- { TYPE_AUTHOR, "auth" },
- { TYPE_CONFIG, "conf" },
- { TYPE_DESC, "desc" },
- { TYPE_XREF, "xref" },
- { TYPE_PATH, "path" },
- { TYPE_ENV, "env" },
- { TYPE_ERR, "err" },
- { INT_MAX, "all" },
+ { TYPE_An, "An" },
+ { TYPE_Cd, "Cd" },
+ { TYPE_Er, "Er" },
+ { TYPE_Ev, "Ev" },
+ { TYPE_Fn, "Fn" },
+ { TYPE_Fn, "Fo" },
+ { TYPE_In, "In" },
+ { TYPE_Nd, "Nd" },
+ { TYPE_Nm, "Nm" },
+ { TYPE_Pa, "Pa" },
+ { TYPE_St, "St" },
+ { TYPE_Va, "Va" },
+ { TYPE_Va, "Vt" },
+ { TYPE_Xr, "Xr" },
+ { INT_MAX, "any" },
{ 0, NULL }
};
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 *);
memset(&info, 0, sizeof(BTREEINFO));
info.flags = R_DUP;
- db = dbopen("mandoc.db", O_RDONLY, 0, DB_BTREE, &info);
+ db = dbopen(MANDOC_DB, O_RDONLY, 0, DB_BTREE, &info);
if (NULL != db)
return(db);
{
DB *db;
- db = dbopen("mandoc.index", O_RDONLY, 0, DB_RECNO, NULL);
+ db = dbopen(MANDOC_IDX, O_RDONLY, 0, DB_RECNO, NULL);
if (NULL != db)
return(db);
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));
}
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));
if (NULL == p)
return;
- if (MATCH_REGEX == p->match)
+ if (p->regex)
regfree(&p->re);
free(p->v);
}
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));
}