summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2011-11-13 11:10:27 +0000
committerIngo Schwarze <schwarze@openbsd.org>2011-11-13 11:10:27 +0000
commite1e948c76eb5817bac9e6e4dbbc30fe62e010f62 (patch)
tree5fac405ee4a36b94824d008fc8fb1ffc50aeca73
parent3b6c23580b17850eb580cf7bf023bd9f04563ca0 (diff)
downloadmandoc-e1e948c76eb5817bac9e6e4dbbc30fe62e010f62.tar.gz
Rewrite the expression parser for a more concise syntax:
apropos [search_type[,...]=]substring apropos search_type[,...][,i]~regex ... and expression evaluation must take the search type into account. This allows to: * drop the global -I option and * drop the enum match, just using a boolean int. "go ahead" kristaps@
-rw-r--r--apropos.c11
-rw-r--r--apropos_db.c106
-rw-r--r--apropos_db.h2
3 files changed, 54 insertions, 65 deletions
diff --git a/apropos.c b/apropos.c
index 6f731c4a..0e3ac42f 100644
--- a/apropos.c
+++ b/apropos.c
@@ -33,7 +33,7 @@ static char *progname;
int
main(int argc, char *argv[])
{
- int ch, cs;
+ int ch;
struct opts opts;
struct expr *e;
extern int optind;
@@ -47,9 +47,7 @@ main(int argc, char *argv[])
else
++progname;
- cs = 0;
-
- while (-1 != (ch = getopt(argc, argv, "S:s:I")))
+ while (-1 != (ch = getopt(argc, argv, "S:s:")))
switch (ch) {
case ('S'):
opts.arch = optarg;
@@ -57,9 +55,6 @@ main(int argc, char *argv[])
case ('s'):
opts.cat = optarg;
break;
- case ('I'):
- cs = 1;
- break;
default:
usage();
return(EXIT_FAILURE);
@@ -71,7 +66,7 @@ main(int argc, char *argv[])
if (0 == argc)
return(EXIT_SUCCESS);
- if (NULL == (e = exprcomp(cs, argv, argc))) {
+ if (NULL == (e = exprcomp(argc, argv))) {
fprintf(stderr, "Bad expression\n");
return(EXIT_FAILURE);
}
diff --git a/apropos_db.c b/apropos_db.c
index 75a5df2d..aa4d54c4 100644
--- a/apropos_db.c
+++ b/apropos_db.c
@@ -1,6 +1,7 @@
/* $Id$ */
/*
* 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
@@ -31,15 +32,8 @@
#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(int argc, char *argv[])
{
struct expr *p;
struct expr e;
- int i, pos, ch;
+ char *key;
+ int i, icase;
- pos = 0;
-
- if (pos > argc)
+ if (0 >= argc)
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(*argv, "=~"))) {
+ e.regex = 0;
+ e.v = *argv;
+ } 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 (*argv < e.v) {
+ while (NULL != (key = strsep(argv, ","))) {
+ 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));
}
diff --git a/apropos_db.h b/apropos_db.h
index 135f6793..6cc14d57 100644
--- a/apropos_db.h
+++ b/apropos_db.h
@@ -49,7 +49,7 @@ void apropos_search(const struct opts *,
const struct expr *, void *,
void (*)(struct rec *, size_t, void *));
-struct expr *exprcomp(int, char *[], int);
+struct expr *exprcomp(int, char *[]);
void exprfree(struct expr *);
__END_DECLS