version 1.5, 2011/11/18 07:02:19 |
version 1.6, 2011/11/20 12:39:08 |
|
|
#include <fcntl.h> |
#include <fcntl.h> |
#include <regex.h> |
#include <regex.h> |
#include <stdarg.h> |
#include <stdarg.h> |
|
#include <stdint.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
|
|
struct expr { |
struct expr { |
int regex; /* is regex? */ |
int regex; /* is regex? */ |
int index; /* index in match array */ |
int index; /* index in match array */ |
int mask; /* type-mask */ |
uint64_t mask; /* type-mask */ |
int cs; /* is case-sensitive? */ |
int cs; /* is case-sensitive? */ |
int and; /* is rhs of logical AND? */ |
int and; /* is rhs of logical AND? */ |
char *v; /* search value */ |
char *v; /* search value */ |
|
|
}; |
}; |
|
|
struct type { |
struct type { |
int mask; |
uint64_t mask; |
const char *name; |
const char *name; |
}; |
}; |
|
|
static const struct type types[] = { |
static const struct type types[] = { |
{ TYPE_An, "An" }, |
{ TYPE_An, "An" }, |
{ TYPE_Cd, "Cd" }, |
{ TYPE_Ar, "Ar" }, |
{ TYPE_Er, "Er" }, |
{ TYPE_At, "At" }, |
{ TYPE_Ev, "Ev" }, |
{ TYPE_Bsx, "Bsx" }, |
{ TYPE_Fn, "Fn" }, |
{ TYPE_Bx, "Bx" }, |
{ TYPE_Fn, "Fo" }, |
{ TYPE_Cd, "Cd" }, |
{ TYPE_In, "In" }, |
{ TYPE_Cm, "Cm" }, |
{ TYPE_Nd, "Nd" }, |
{ TYPE_Dv, "Dv" }, |
{ TYPE_Nm, "Nm" }, |
{ TYPE_Dx, "Dx" }, |
{ TYPE_Pa, "Pa" }, |
{ TYPE_Em, "Em" }, |
{ TYPE_St, "St" }, |
{ TYPE_Er, "Er" }, |
{ TYPE_Va, "Va" }, |
{ TYPE_Ev, "Ev" }, |
{ TYPE_Va, "Vt" }, |
{ TYPE_Fa, "Fa" }, |
{ TYPE_Xr, "Xr" }, |
{ TYPE_Fl, "Fl" }, |
|
{ TYPE_Fn, "Fn" }, |
|
{ TYPE_Fn, "Fo" }, |
|
{ TYPE_Ft, "Ft" }, |
|
{ TYPE_Fx, "Fx" }, |
|
{ TYPE_Ic, "Ic" }, |
|
{ TYPE_In, "In" }, |
|
{ TYPE_Lb, "Lb" }, |
|
{ TYPE_Li, "Li" }, |
|
{ TYPE_Lk, "Lk" }, |
|
{ TYPE_Ms, "Ms" }, |
|
{ TYPE_Mt, "Mt" }, |
|
{ TYPE_Nd, "Nd" }, |
|
{ TYPE_Nm, "Nm" }, |
|
{ TYPE_Nx, "Nx" }, |
|
{ TYPE_Ox, "Ox" }, |
|
{ TYPE_Pa, "Pa" }, |
|
{ TYPE_Rs, "Rs" }, |
|
{ TYPE_Sh, "Sh" }, |
|
{ TYPE_Ss, "Ss" }, |
|
{ TYPE_St, "St" }, |
|
{ TYPE_Sy, "Sy" }, |
|
{ TYPE_Tn, "Tn" }, |
|
{ TYPE_Va, "Va" }, |
|
{ TYPE_Va, "Vt" }, |
|
{ TYPE_Xr, "Xr" }, |
{ INT_MAX, "any" }, |
{ INT_MAX, "any" }, |
{ 0, NULL } |
{ 0, NULL } |
}; |
}; |
Line 87 static int btree_read(const DBT *, |
|
Line 113 static int btree_read(const DBT *, |
|
const struct mchars *, char **); |
const struct mchars *, char **); |
static int expreval(const struct expr *, int *); |
static int expreval(const struct expr *, int *); |
static void exprexec(const struct expr *, |
static void exprexec(const struct expr *, |
const char *, int, struct rec *); |
const char *, uint64_t, struct rec *); |
static int exprmark(const struct expr *, |
static int exprmark(const struct expr *, |
const char *, int, int *); |
const char *, uint64_t, int *); |
static struct expr *exprexpr(int, char *[], int *, int *, size_t *); |
static struct expr *exprexpr(int, char *[], int *, int *, size_t *); |
static struct expr *exprterm(char *, int); |
static struct expr *exprterm(char *, int); |
static DB *index_open(void); |
static DB *index_open(void); |
Line 130 btree_read(const DBT *v, const struct mchars *mc, char |
|
Line 156 btree_read(const DBT *v, const struct mchars *mc, char |
|
/* Sanity: are we nil-terminated? */ |
/* Sanity: are we nil-terminated? */ |
|
|
assert(v->size > 0); |
assert(v->size > 0); |
|
|
if ('\0' != ((char *)v->data)[(int)v->size - 1]) |
if ('\0' != ((char *)v->data)[(int)v->size - 1]) |
return(0); |
return(0); |
|
|
Line 348 apropos_search(const struct opts *opts, const struct e |
|
Line 375 apropos_search(const struct opts *opts, const struct e |
|
size_t terms, void *arg, |
size_t terms, void *arg, |
void (*res)(struct res *, size_t, void *)) |
void (*res)(struct res *, size_t, void *)) |
{ |
{ |
int i, rsz, root, leaf, mask, mlen, rc, ch; |
int i, rsz, root, leaf, mlen, rc, ch; |
|
uint64_t mask; |
DBT key, val; |
DBT key, val; |
DB *btree, *idx; |
DB *btree, *idx; |
struct mchars *mc; |
struct mchars *mc; |
Line 357 apropos_search(const struct opts *opts, const struct e |
|
Line 385 apropos_search(const struct opts *opts, const struct e |
|
struct rec *rs; |
struct rec *rs; |
struct res *ress; |
struct res *ress; |
struct rec r; |
struct rec r; |
|
struct db_val *vbuf; |
|
|
rc = 0; |
rc = 0; |
root = -1; |
root = -1; |
Line 378 apropos_search(const struct opts *opts, const struct e |
|
Line 407 apropos_search(const struct opts *opts, const struct e |
|
goto out; |
goto out; |
|
|
while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) { |
while (0 == (ch = (*btree->seq)(btree, &key, &val, R_NEXT))) { |
/* |
if (key.size < 2 || sizeof(struct db_val) != val.size) |
* Low-water mark for key and value. |
break; |
* The key must have something in it, and the value must |
|
* have the correct tags/recno mix. |
|
*/ |
|
if (key.size < 2 || 8 != val.size) |
|
break; |
|
if ( ! btree_read(&key, mc, &buf)) |
if ( ! btree_read(&key, mc, &buf)) |
break; |
break; |
|
|
mask = *(int *)val.data; |
vbuf = val.data; |
|
rec = vbuf->rec; |
|
mask = vbuf->mask; |
|
|
/* |
/* |
* See if this keyword record matches any of the |
* See if this keyword record matches any of the |
Line 397 apropos_search(const struct opts *opts, const struct e |
|
Line 423 apropos_search(const struct opts *opts, const struct e |
|
if ( ! exprmark(expr, buf, mask, NULL)) |
if ( ! exprmark(expr, buf, mask, NULL)) |
continue; |
continue; |
|
|
memcpy(&rec, val.data + 4, sizeof(recno_t)); |
|
|
|
/* |
/* |
* O(log n) scan for prior records. Since a record |
* O(log n) scan for prior records. Since a record |
* number is unbounded, this has decent performance over |
* number is unbounded, this has decent performance over |
Line 701 exprfree(struct expr *p) |
|
Line 725 exprfree(struct expr *p) |
|
} |
} |
|
|
static int |
static int |
exprmark(const struct expr *p, const char *cp, int mask, int *ms) |
exprmark(const struct expr *p, const char *cp, |
|
uint64_t mask, int *ms) |
{ |
{ |
|
|
for ( ; p; p = p->next) { |
for ( ; p; p = p->next) { |
Line 772 expreval(const struct expr *p, int *ms) |
|
Line 797 expreval(const struct expr *p, int *ms) |
|
* If this evaluates to true, mark the expression as satisfied. |
* If this evaluates to true, mark the expression as satisfied. |
*/ |
*/ |
static void |
static void |
exprexec(const struct expr *p, const char *cp, int mask, struct rec *r) |
exprexec(const struct expr *p, const char *cp, |
|
uint64_t mask, struct rec *r) |
{ |
{ |
|
|
assert(0 == r->matched); |
assert(0 == r->matched); |