version 1.2, 2011/11/13 10:49:57 |
version 1.3, 2011/11/13 11:10:27 |
|
|
/* $Id$ */ |
/* $Id$ */ |
/* |
/* |
* Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> |
* 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 |
* Permission to use, copy, modify, and distribute this software for any |
* purpose with or without fee is hereby granted, provided that the above |
* purpose with or without fee is hereby granted, provided that the above |
|
|
#include "apropos_db.h" |
#include "apropos_db.h" |
#include "mandoc.h" |
#include "mandoc.h" |
|
|
enum match { |
|
MATCH_REGEX, |
|
MATCH_REGEXCASE, |
|
MATCH_STR, |
|
MATCH_STRCASE |
|
}; |
|
|
|
struct expr { |
struct expr { |
enum match match; |
int regex; |
int mask; |
int mask; |
char *v; |
char *v; |
regex_t re; |
regex_t re; |
Line 71 static const struct type types[] = { |
|
Line 65 static const struct type types[] = { |
|
|
|
static DB *btree_open(void); |
static DB *btree_open(void); |
static int btree_read(const DBT *, const struct mchars *, char **); |
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 DB *index_open(void); |
static int index_read(const DBT *, const DBT *, |
static int index_read(const DBT *, const DBT *, |
const struct mchars *, struct rec *); |
const struct mchars *, struct rec *); |
Line 368 apropos_search(const struct opts *opts, const struct e |
|
Line 362 apropos_search(const struct opts *opts, const struct e |
|
if ( ! btree_read(&key, mc, &buf)) |
if ( ! btree_read(&key, mc, &buf)) |
break; |
break; |
|
|
if ( ! exprexec(expr, buf)) |
if ( ! exprexec(expr, buf, *(int *)val.data)) |
continue; |
continue; |
|
|
memcpy(&rec, val.data + 4, sizeof(recno_t)); |
memcpy(&rec, val.data + 4, sizeof(recno_t)); |
|
|
} |
} |
|
|
struct expr * |
struct expr * |
exprcomp(int cs, char *argv[], int argc) |
exprcomp(int argc, char *argv[]) |
{ |
{ |
struct expr *p; |
struct expr *p; |
struct expr e; |
struct expr e; |
int i, pos, ch; |
char *key; |
|
int i, icase; |
|
|
pos = 0; |
if (0 >= argc) |
|
|
if (pos > argc) |
|
return(NULL); |
return(NULL); |
|
|
for (i = 0; 0 != types[i].mask; i++) |
/* |
if (0 == strcmp(types[i].name, argv[pos])) |
* Choose regex or substring match. |
break; |
*/ |
|
|
if (0 == (e.mask = types[i].mask)) |
if (NULL == (e.v = strpbrk(*argv, "=~"))) { |
return(NULL); |
e.regex = 0; |
|
e.v = *argv; |
|
} else { |
|
e.regex = '~' == *e.v; |
|
*e.v++ = '\0'; |
|
} |
|
|
if (++pos > argc--) |
/* |
return(NULL); |
* Determine the record types to search for. |
|
*/ |
|
|
if ('-' != *argv[pos]) |
icase = 0; |
e.match = cs ? MATCH_STRCASE : MATCH_STR; |
e.mask = 0; |
else if (0 == strcmp("-eq", argv[pos])) |
if (*argv < e.v) { |
e.match = cs ? MATCH_STRCASE : MATCH_STR; |
while (NULL != (key = strsep(argv, ","))) { |
else if (0 == strcmp("-ieq", argv[pos])) |
if ('i' == key[0] && '\0' == key[1]) { |
e.match = MATCH_STRCASE; |
icase = REG_ICASE; |
else if (0 == strcmp("-re", argv[pos])) |
continue; |
e.match = cs ? MATCH_REGEXCASE : MATCH_REGEX; |
} |
else if (0 == strcmp("-ire", argv[pos])) |
i = 0; |
e.match = MATCH_REGEXCASE; |
while (types[i].mask && |
else |
strcmp(types[i].name, key)) |
return(NULL); |
i++; |
|
e.mask |= types[i].mask; |
|
} |
|
} |
|
if (0 == e.mask) |
|
e.mask = TYPE_Nm | TYPE_Nd; |
|
|
if ('-' == *argv[pos]) |
if (e.regex && |
pos++; |
regcomp(&e.re, e.v, REG_EXTENDED | REG_NOSUB | icase)) |
|
|
if (pos > argc--) |
|
return(NULL); |
return(NULL); |
|
|
e.v = mandoc_strdup(argv[pos]); |
e.v = mandoc_strdup(e.v); |
|
|
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)); |
p = mandoc_calloc(1, sizeof(struct expr)); |
memcpy(p, &e, sizeof(struct expr)); |
memcpy(p, &e, sizeof(struct expr)); |
return(p); |
return(p); |
Line 522 exprfree(struct expr *p) |
|
Line 516 exprfree(struct expr *p) |
|
if (NULL == p) |
if (NULL == p) |
return; |
return; |
|
|
if (MATCH_REGEX == p->match) |
if (p->regex) |
regfree(&p->re); |
regfree(&p->re); |
|
|
free(p->v); |
free(p->v); |
Line 530 exprfree(struct expr *p) |
|
Line 524 exprfree(struct expr *p) |
|
} |
} |
|
|
static int |
static int |
exprexec(const struct expr *p, char *cp) |
exprexec(const struct expr *p, char *cp, int mask) |
{ |
{ |
|
|
if (MATCH_STR == p->match) |
if ( ! (mask & p->mask)) |
return(0 == strcmp(p->v, cp)); |
return(0); |
else if (MATCH_STRCASE == p->match) |
|
return(0 == strcasecmp(p->v, cp)); |
|
|
|
assert(MATCH_REGEX == p->match); |
if (p->regex) |
return(0 == regexec(&p->re, cp, 0, NULL, 0)); |
return(0 == regexec(&p->re, cp, 0, NULL, 0)); |
|
else |
|
return(NULL != strcasestr(cp, p->v)); |
} |
} |