From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from krisdoz.my.domain (kristaps@localhost [127.0.0.1]) by krisdoz.my.domain (8.14.3/8.14.3) with ESMTP id pA9M5u70011909 for ; Wed, 9 Nov 2011 17:05:57 -0500 (EST) Received: (from kristaps@localhost) by krisdoz.my.domain (8.14.3/8.14.3/Submit) id pA9M5uL6016395; Wed, 9 Nov 2011 17:05:56 -0500 (EST) Date: Wed, 9 Nov 2011 17:05:56 -0500 (EST) Message-Id: <201111092205.pA9M5uL6016395@krisdoz.my.domain> X-Mailinglist: mdocml-source Reply-To: source@mdocml.bsd.lv MIME-Version: 1.0 From: kristaps@mdocml.bsd.lv To: source@mdocml.bsd.lv Subject: mdocml: Make apropos's lookup use a find(1)-like expression. X-Mailer: activitymail 1.26, http://search.cpan.org/dist/activitymail/ Content-Type: text/plain; charset=utf-8 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(")"); } } +#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