* mdocml: Make apropos's lookup use a find(1)-like expression.
@ 2011-11-09 22:05 kristaps
0 siblings, 0 replies; only message in thread
From: kristaps @ 2011-11-09 22:05 UTC (permalink / raw)
To: source
Log Message:
-----------
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.
Modified Files:
--------------
mdocml:
apropos.c
apropos.h
cgi.c
db.c
Revision Data
-------------
Index: cgi.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/cgi.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lcgi.c -Lcgi.c -u -p -r1.1 -r1.2
--- cgi.c
+++ cgi.c
@@ -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__
"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 *pa
}
+#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
puts(")</A>");
}
}
+#endif
static void
pg_search(const struct req *req, char *path)
@@ -238,8 +246,8 @@ pg_search(const struct req *req, char *p
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
Index: apropos.h
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -Lapropos.h -Lapropos.h -u -p -r1.1 -r1.2
--- apropos.h
+++ apropos.h
@@ -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
Index: apropos.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/apropos.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -Lapropos.c -Lapropos.c -u -p -r1.9 -r1.10
--- apropos.c
+++ apropos.c
@@ -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);
}
Index: db.c
===================================================================
RCS file: /usr/vhosts/mdocml.bsd.lv/cvs/mdocml/db.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -Ldb.c -Ldb.c -u -p -r1.1 -r1.2
--- db.c
+++ db.c
@@ -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 *va
}
/*
- * 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,
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(®, 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,
*/
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(®, 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(®);
+}
+
+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));
}
--
To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-11-09 22:05 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-09 22:05 mdocml: Make apropos's lookup use a find(1)-like expression kristaps
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).