+static void dbclose(const char *, int);
+static void dbindex(struct mchars *, int,
+ const struct of *, const char *);
+static int dbopen(const char *, int);
+static void dbprune(const char *);
+static void fileadd(struct of *);
+static int filecheck(const char *);
+static void filescan(const char *, const char *);
+static struct str *hashget(const char *, size_t);
+static void *hash_alloc(size_t, void *);
+static void hash_free(void *, size_t, void *);
+static void *hash_halloc(size_t, void *);
+static void inoadd(const struct stat *, struct of *);
+static int inocheck(const struct stat *);
+static void ofadd(const char *, int, const char *,
+ const char *, const char *, const char *,
+ const char *, const struct stat *);
+static void offree(void);
+static int ofmerge(struct mchars *, struct mparse *, const char *);
+static void parse_catpage(struct of *, const char *);
+static int parse_man(struct of *,
+ const struct man_node *);
+static void parse_mdoc(struct of *, const struct mdoc_node *);
+static int parse_mdoc_body(struct of *, const struct mdoc_node *);
+static int parse_mdoc_head(struct of *, const struct mdoc_node *);
+static int parse_mdoc_Fd(struct of *, const struct mdoc_node *);
+static int parse_mdoc_Fn(struct of *, const struct mdoc_node *);
+static int parse_mdoc_In(struct of *, const struct mdoc_node *);
+static int parse_mdoc_Nd(struct of *, const struct mdoc_node *);
+static int parse_mdoc_Nm(struct of *, const struct mdoc_node *);
+static int parse_mdoc_Sh(struct of *, const struct mdoc_node *);
+static int parse_mdoc_St(struct of *, const struct mdoc_node *);
+static int parse_mdoc_Xr(struct of *, const struct mdoc_node *);
+static int path_reset(const char *, int, const char *);
+static void putkey(const struct of *,
+ const char *, uint64_t);
+static void putkeys(const struct of *,
+ const char *, int, uint64_t);
+static void putmdockey(const struct of *,
+ const struct mdoc_node *, uint64_t);
+static char *stradd(const char *);
+static char *straddbuf(const char *, size_t);
+static int treescan(const char *);
+static size_t utf8(unsigned int, char [7]);
+static void utf8key(struct mchars *, struct str *);
+static void wordaddbuf(const struct of *,
+ const char *, size_t, uint64_t);
+
+static char *progname;
+static int use_all; /* use all found files */
+static int nodb; /* no database changes */
+static int verb; /* print what we're doing */
+static int warnings; /* warn about crap */
+static enum op op; /* operational mode */
+static struct ohash inos; /* table of inodes/devices */
+static struct ohash filenames; /* table of filenames */
+static struct ohash strings; /* table of all strings */
+static struct of *ofs = NULL; /* vector of files to parse */
+static struct str *words = NULL; /* word list in current parse */
+static sqlite3 *db = NULL; /* current database */
+static sqlite3_stmt *stmts[STMT__MAX]; /* current statements */
+
+static const struct mdoc_handler mdocs[MDOC_MAX] = {
+ { NULL, 0, 0 }, /* Ap */
+ { NULL, 0, 0 }, /* Dd */
+ { NULL, 0, 0 }, /* Dt */
+ { NULL, 0, 0 }, /* Os */
+ { parse_mdoc_Sh, TYPE_Sh, MDOCF_CHILD }, /* Sh */
+ { parse_mdoc_head, TYPE_Ss, MDOCF_CHILD }, /* Ss */
+ { NULL, 0, 0 }, /* Pp */
+ { NULL, 0, 0 }, /* D1 */
+ { NULL, 0, 0 }, /* Dl */
+ { NULL, 0, 0 }, /* Bd */
+ { NULL, 0, 0 }, /* Ed */
+ { NULL, 0, 0 }, /* Bl */
+ { NULL, 0, 0 }, /* El */
+ { NULL, 0, 0 }, /* It */
+ { NULL, 0, 0 }, /* Ad */
+ { NULL, TYPE_An, MDOCF_CHILD }, /* An */
+ { NULL, TYPE_Ar, MDOCF_CHILD }, /* Ar */
+ { NULL, TYPE_Cd, MDOCF_CHILD }, /* Cd */
+ { NULL, TYPE_Cm, MDOCF_CHILD }, /* Cm */
+ { NULL, TYPE_Dv, MDOCF_CHILD }, /* Dv */
+ { NULL, TYPE_Er, MDOCF_CHILD }, /* Er */
+ { NULL, TYPE_Ev, MDOCF_CHILD }, /* Ev */
+ { NULL, 0, 0 }, /* Ex */
+ { NULL, TYPE_Fa, MDOCF_CHILD }, /* Fa */
+ { parse_mdoc_Fd, TYPE_In, 0 }, /* Fd */
+ { NULL, TYPE_Fl, MDOCF_CHILD }, /* Fl */
+ { parse_mdoc_Fn, 0, 0 }, /* Fn */
+ { NULL, TYPE_Ft, MDOCF_CHILD }, /* Ft */
+ { NULL, TYPE_Ic, MDOCF_CHILD }, /* Ic */
+ { parse_mdoc_In, TYPE_In, MDOCF_CHILD }, /* In */
+ { NULL, TYPE_Li, MDOCF_CHILD }, /* Li */
+ { parse_mdoc_Nd, TYPE_Nd, MDOCF_CHILD }, /* Nd */
+ { parse_mdoc_Nm, TYPE_Nm, MDOCF_CHILD }, /* Nm */
+ { NULL, 0, 0 }, /* Op */
+ { NULL, 0, 0 }, /* Ot */
+ { NULL, TYPE_Pa, MDOCF_CHILD }, /* Pa */
+ { NULL, 0, 0 }, /* Rv */
+ { parse_mdoc_St, TYPE_St, 0 }, /* St */
+ { NULL, TYPE_Va, MDOCF_CHILD }, /* Va */
+ { parse_mdoc_body, TYPE_Va, MDOCF_CHILD }, /* Vt */
+ { parse_mdoc_Xr, TYPE_Xr, 0 }, /* Xr */
+ { NULL, 0, 0 }, /* %A */
+ { NULL, 0, 0 }, /* %B */
+ { NULL, 0, 0 }, /* %D */
+ { NULL, 0, 0 }, /* %I */
+ { NULL, 0, 0 }, /* %J */
+ { NULL, 0, 0 }, /* %N */
+ { NULL, 0, 0 }, /* %O */
+ { NULL, 0, 0 }, /* %P */
+ { NULL, 0, 0 }, /* %R */
+ { NULL, 0, 0 }, /* %T */
+ { NULL, 0, 0 }, /* %V */
+ { NULL, 0, 0 }, /* Ac */
+ { NULL, 0, 0 }, /* Ao */
+ { NULL, 0, 0 }, /* Aq */
+ { NULL, TYPE_At, MDOCF_CHILD }, /* At */
+ { NULL, 0, 0 }, /* Bc */
+ { NULL, 0, 0 }, /* Bf */
+ { NULL, 0, 0 }, /* Bo */
+ { NULL, 0, 0 }, /* Bq */
+ { NULL, TYPE_Bsx, MDOCF_CHILD }, /* Bsx */
+ { NULL, TYPE_Bx, MDOCF_CHILD }, /* Bx */
+ { NULL, 0, 0 }, /* Db */
+ { NULL, 0, 0 }, /* Dc */
+ { NULL, 0, 0 }, /* Do */
+ { NULL, 0, 0 }, /* Dq */
+ { NULL, 0, 0 }, /* Ec */
+ { NULL, 0, 0 }, /* Ef */
+ { NULL, TYPE_Em, MDOCF_CHILD }, /* Em */
+ { NULL, 0, 0 }, /* Eo */
+ { NULL, TYPE_Fx, MDOCF_CHILD }, /* Fx */
+ { NULL, TYPE_Ms, MDOCF_CHILD }, /* Ms */
+ { NULL, 0, 0 }, /* No */
+ { NULL, 0, 0 }, /* Ns */
+ { NULL, TYPE_Nx, MDOCF_CHILD }, /* Nx */
+ { NULL, TYPE_Ox, MDOCF_CHILD }, /* Ox */
+ { NULL, 0, 0 }, /* Pc */
+ { NULL, 0, 0 }, /* Pf */
+ { NULL, 0, 0 }, /* Po */
+ { NULL, 0, 0 }, /* Pq */
+ { NULL, 0, 0 }, /* Qc */
+ { NULL, 0, 0 }, /* Ql */
+ { NULL, 0, 0 }, /* Qo */
+ { NULL, 0, 0 }, /* Qq */
+ { NULL, 0, 0 }, /* Re */
+ { NULL, 0, 0 }, /* Rs */
+ { NULL, 0, 0 }, /* Sc */
+ { NULL, 0, 0 }, /* So */
+ { NULL, 0, 0 }, /* Sq */
+ { NULL, 0, 0 }, /* Sm */
+ { NULL, 0, 0 }, /* Sx */
+ { NULL, TYPE_Sy, MDOCF_CHILD }, /* Sy */
+ { NULL, TYPE_Tn, MDOCF_CHILD }, /* Tn */
+ { NULL, 0, 0 }, /* Ux */
+ { NULL, 0, 0 }, /* Xc */
+ { NULL, 0, 0 }, /* Xo */
+ { parse_mdoc_head, TYPE_Fn, 0 }, /* Fo */
+ { NULL, 0, 0 }, /* Fc */
+ { NULL, 0, 0 }, /* Oo */
+ { NULL, 0, 0 }, /* Oc */
+ { NULL, 0, 0 }, /* Bk */
+ { NULL, 0, 0 }, /* Ek */
+ { NULL, 0, 0 }, /* Bt */
+ { NULL, 0, 0 }, /* Hf */
+ { NULL, 0, 0 }, /* Fr */
+ { NULL, 0, 0 }, /* Ud */
+ { NULL, TYPE_Lb, MDOCF_CHILD }, /* Lb */
+ { NULL, 0, 0 }, /* Lp */
+ { NULL, TYPE_Lk, MDOCF_CHILD }, /* Lk */
+ { NULL, TYPE_Mt, MDOCF_CHILD }, /* Mt */
+ { NULL, 0, 0 }, /* Brq */
+ { NULL, 0, 0 }, /* Bro */
+ { NULL, 0, 0 }, /* Brc */
+ { NULL, 0, 0 }, /* %C */
+ { NULL, 0, 0 }, /* Es */
+ { NULL, 0, 0 }, /* En */
+ { NULL, TYPE_Dx, MDOCF_CHILD }, /* Dx */
+ { NULL, 0, 0 }, /* %Q */
+ { NULL, 0, 0 }, /* br */
+ { NULL, 0, 0 }, /* sp */
+ { NULL, 0, 0 }, /* %U */
+ { NULL, 0, 0 }, /* Ta */