aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorKristaps Dzonsons <kristaps@bsd.lv>2011-11-09 22:05:56 +0000
committerKristaps Dzonsons <kristaps@bsd.lv>2011-11-09 22:05:56 +0000
commit53ecc54dbae535c524e2b4044ae5c358dcd67c30 (patch)
tree2eb8acec92b0c4fbc2e618a02b4e5f90cbad6bda
parent3089a1b55afe00d988cd16b8de6fe2cd08ff48f5 (diff)
downloadmandoc-53ecc54dbae535c524e2b4044ae5c358dcd67c30.tar.gz
mandoc-53ecc54dbae535c524e2b4044ae5c358dcd67c30.tar.zst
mandoc-53ecc54dbae535c524e2b4044ae5c358dcd67c30.zip
Make apropos's lookup use a find(1)-like expression. I'll write more on
this when it completes; this is to keep it in-tree. Right now this uses prefix notation. Ignore it. I'll make this into infix notation real soon. The goal of this (exprcomp and exprexec) is to have arbitrary logical expressions.
-rw-r--r--apropos.c73
-rw-r--r--apropos.h15
-rw-r--r--cgi.c14
-rw-r--r--db.c136
4 files changed, 150 insertions, 88 deletions
diff --git a/apropos.c b/apropos.c
index 4e438e99..6bb5b7a9 100644
--- a/apropos.c
+++ b/apropos.c
@@ -1,4 +1,4 @@
-/* $Id: apropos.c,v 1.9 2011/11/09 10:53:48 kristaps Exp $ */
+/* $Id: apropos.c,v 1.10 2011/11/09 22:05:56 kristaps Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -24,29 +24,6 @@
#include "apropos.h"
#include "mandoc.h"
-struct type {
- int mask;
- const char *name; /* command-line type name */
-};
-
-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" },
- { 0, NULL }
-};
-
static int cmp(const void *, const void *);
static void list(struct rec *, size_t, void *);
static void usage(void);
@@ -56,23 +33,23 @@ static char *progname;
int
main(int argc, char *argv[])
{
- int ch, i;
- char *q, *v;
+ int ch, cs;
struct opts opts;
+ struct expr *e;
extern int optind;
extern char *optarg;
memset(&opts, 0, sizeof(struct opts));
- q = NULL;
-
progname = strrchr(argv[0], '/');
if (progname == NULL)
progname = argv[0];
else
++progname;
- while (-1 != (ch = getopt(argc, argv, "S:s:It:")))
+ cs = 0;
+
+ while (-1 != (ch = getopt(argc, argv, "S:s:I")))
switch (ch) {
case ('S'):
opts.arch = optarg;
@@ -81,26 +58,8 @@ main(int argc, char *argv[])
opts.cat = optarg;
break;
case ('I'):
- opts.flags |= OPTS_INSENS;
+ cs = 1;
break;
- case ('t'):
- while (NULL != (v = strsep(&optarg, ","))) {
- if ('\0' == *v)
- continue;
- for (i = 0; types[i].mask; i++) {
- if (strcmp(types[i].name, v))
- continue;
- break;
- }
- if (0 == types[i].mask)
- break;
- opts.types |= types[i].mask;
- }
- if (NULL == v)
- break;
-
- fprintf(stderr, "%s: Bad type\n", v);
- return(EXIT_FAILURE);
default:
usage();
return(EXIT_FAILURE);
@@ -109,14 +68,13 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
- if (0 == argc || '\0' == **argv) {
- usage();
+ if (0 == argc)
return(EXIT_SUCCESS);
- } else
- q = *argv;
- if (0 == opts.types)
- opts.types = TYPE_NAME | TYPE_DESC;
+ if (NULL == (e = exprcomp(cs, argv, argc))) {
+ fprintf(stderr, "Bad expression\n");
+ return(EXIT_FAILURE);
+ }
/*
* Configure databases.
@@ -125,7 +83,8 @@ main(int argc, char *argv[])
* The index database is a recno.
*/
- apropos_search(&opts, q, NULL, list);
+ apropos_search(&opts, e, NULL, list);
+ exprfree(e);
return(EXIT_SUCCESS);
}
@@ -161,6 +120,6 @@ usage(void)
"[-I] "
"[-S arch] "
"[-s section] "
- "[-t type[,...]] "
- "key\n", progname);
+ "EXPR\n",
+ progname);
}
diff --git a/apropos.h b/apropos.h
index 4a06db87..16ebcda2 100644
--- a/apropos.h
+++ b/apropos.h
@@ -1,4 +1,4 @@
-/* $Id: apropos.h,v 1.1 2011/11/09 01:24:23 kristaps Exp $ */
+/* $Id: apropos.h,v 1.2 2011/11/09 22:05:56 kristaps Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -53,15 +53,18 @@ struct rec {
struct opts {
const char *arch; /* restrict to architecture */
const char *cat; /* restrict to manual section */
- int types; /* only types in bitmask */
- int flags;
-#define OPTS_INSENS (0x01) /* case-insensitive match */
};
__BEGIN_DECLS
-void apropos_search(const struct opts *, const char *,
- void *, void (*)(struct rec *, size_t, void *));
+struct expr;
+
+void apropos_search(const struct opts *,
+ const struct expr *, void *,
+ void (*)(struct rec *, size_t, void *));
+
+struct expr *exprcomp(int, char *[], int);
+void exprfree(struct expr *);
__END_DECLS
diff --git a/cgi.c b/cgi.c
index edf63f8d..a596254a 100644
--- a/cgi.c
+++ b/cgi.c
@@ -1,4 +1,4 @@
-/* $Id: cgi.c,v 1.1 2011/11/09 01:24:23 kristaps Exp $ */
+/* $Id: cgi.c,v 1.2 2011/11/09 22:05:56 kristaps Exp $ */
#include <assert.h>
#include <fcntl.h>
#include <regex.h>
@@ -47,13 +47,17 @@ struct req {
enum page page;
};
+#if 0
static void html_printtext(const char *);
+#endif
static int kval_decode(char *);
static void kval_parse(struct kval **, size_t *, char *);
static void kval_free(struct kval *, size_t);
static void pg_index(const struct req *, char *);
static void pg_search(const struct req *, char *);
+#if 0
static void pg_searchres(struct rec *, size_t, void *);
+#endif
static const char * const pages[PAGE__MAX] = {
"index", /* PAGE_INDEX */
@@ -64,6 +68,7 @@ static const char * const medias[MEDIA__MAX] = {
"html", /* MEDIA_HTML */
};
+#if 0
static void
html_printtext(const char *p)
{
@@ -88,6 +93,7 @@ html_printtext(const char *p)
break;
}
}
+#endif
static void
kval_free(struct kval *p, size_t sz)
@@ -205,6 +211,7 @@ pg_index(const struct req *req, char *path)
}
+#if 0
static void
pg_searchres(struct rec *recs, size_t sz, void *arg)
{
@@ -223,6 +230,7 @@ pg_searchres(struct rec *recs, size_t sz, void *arg)
puts(")</A>");
}
}
+#endif
static void
pg_search(const struct req *req, char *path)
@@ -238,8 +246,8 @@ pg_search(const struct req *req, char *path)
return;
memset(&opt, 0, sizeof(struct opts));
- opt.types = TYPE_NAME | TYPE_DESC;
- apropos_search(&opt, req->fields[i].val, NULL, pg_searchres);
+ /*opt.types = TYPE_NAME | TYPE_DESC;
+ apropos_search(&opt, req->fields[i].val, NULL, pg_searchres);*/
}
int
diff --git a/db.c b/db.c
index adba3eb1..512c48aa 100644
--- a/db.c
+++ b/db.c
@@ -1,4 +1,4 @@
-/* $Id: db.c,v 1.1 2011/11/09 01:24:23 kristaps Exp $ */
+/* $Id: db.c,v 1.2 2011/11/09 22:05:56 kristaps Exp $ */
/*
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
*
@@ -30,8 +30,46 @@
#include "apropos.h"
#include "mandoc.h"
+enum match {
+ MATCH_REGEX,
+ MATCH_REGEXCASE,
+ MATCH_STR,
+ MATCH_STRCASE
+};
+
+struct expr {
+ enum match match;
+ int mask;
+ char *v;
+ regex_t re;
+};
+
+struct type {
+ int mask;
+ const char *name;
+};
+
+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" },
+ { 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 DB *index_open(void);
static int index_read(const DBT *, const DBT *,
const struct mchars *, struct rec *);
@@ -277,16 +315,15 @@ index_read(const DBT *key, const DBT *val,
}
/*
- * Search the mandocdb database for the regular expression "q".
+ * Search the mandocdb database for the expression "expr".
* Filter out by "opts".
* Call "res" with the results, which may be zero.
*/
void
-apropos_search(const struct opts *opts, const char *q, void *arg,
- void (*res)(struct rec *, size_t, void *))
+apropos_search(const struct opts *opts, const struct expr *expr,
+ void *arg, void (*res)(struct rec *, size_t, void *))
{
int i, len, root, leaf;
- regex_t reg;
DBT key, val;
DB *btree, *idx;
struct mchars *mc;
@@ -307,19 +344,8 @@ apropos_search(const struct opts *opts, const char *q, void *arg,
memset(&srec, 0, sizeof(struct rec));
- if (NULL != q && '\0' == *q)
- q = NULL;
-
- ch = REG_EXTENDED | REG_NOSUB |
- (OPTS_INSENS & opts->flags ? REG_ICASE : 0);
-
/* XXX: error out with bad regexp? */
- if (NULL == q || regcomp(&reg, q, ch)) {
- (*res)(NULL, 0, arg);
- return;
- }
-
mc = mchars_alloc();
/* XXX: return fact that we've errored? */
@@ -337,13 +363,10 @@ apropos_search(const struct opts *opts, const char *q, void *arg,
*/
if (key.size < 2 || 8 != val.size)
break;
-
- if ( ! (*(int32_t *)val.data & opts->types))
- continue;
-
if ( ! btree_read(&key, mc, &buf))
break;
- if (regexec(&reg, buf, 0, NULL, 0))
+
+ if ( ! exprexec(expr, buf))
continue;
memcpy(&rec, val.data + 4, sizeof(recno_t));
@@ -432,5 +455,74 @@ out:
free(buf);
free(recs);
- regfree(&reg);
+}
+
+struct expr *
+exprcomp(int cs, char *argv[], int argc)
+{
+ struct expr *p;
+ struct expr e;
+ int i, ch;
+
+ if (3 != argc)
+ return(NULL);
+
+ if (0 == strcmp("-eq", argv[0]))
+ e.match = cs ? MATCH_STRCASE : MATCH_STR;
+ else if (0 == strcmp("-ieq", argv[0]))
+ e.match = MATCH_STRCASE;
+ else if (0 == strcmp("-re", argv[0]))
+ e.match = cs ? MATCH_REGEXCASE : MATCH_REGEX;
+ else if (0 == strcmp("-ire", argv[0]))
+ e.match = MATCH_REGEXCASE;
+ else
+ return(NULL);
+
+ for (i = 0; 0 != types[i].mask; i++)
+ if (0 == strcmp(types[i].name, argv[1]))
+ break;
+
+ if (0 == (e.mask = types[i].mask))
+ return(NULL);
+
+ e.v = mandoc_strdup(argv[2]);
+
+ 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);
+ }
+
+ p = mandoc_calloc(1, sizeof(struct expr));
+ memcpy(p, &e, sizeof(struct expr));
+ return(p);
+}
+
+void
+exprfree(struct expr *p)
+{
+
+ if (NULL == p)
+ return;
+
+ if (MATCH_REGEX == p->match)
+ regfree(&p->re);
+
+ free(p->v);
+ free(p);
+}
+
+static int
+exprexec(const struct expr *p, char *cp)
+{
+
+ if (MATCH_STR == p->match)
+ return(0 == strcmp(p->v, cp));
+ else if (MATCH_STRCASE == p->match)
+ return(0 == strcasecmp(p->v, cp));
+
+ assert(MATCH_REGEX == p->match);
+ return(0 == regexec(&p->re, cp, 0, NULL, 0));
}