+static void dbclose(int);
+static void dbindex(const struct mpage *, struct mchars *);
+static int dbopen(int);
+static void dbprune(void);
+static void filescan(const char *);
+static void *hash_alloc(size_t, void *);
+static void hash_free(void *, size_t, void *);
+static void *hash_halloc(size_t, void *);
+static void mlink_add(struct mlink *, const struct stat *);
+static void mlink_free(struct mlink *);
+static void mlinks_undupe(struct mpage *);
+static void mpages_free(void);
+static void mpages_merge(struct mchars *, struct mparse *, int);
+static void parse_cat(struct mpage *);
+static void parse_man(struct mpage *, const struct man_node *);
+static void parse_mdoc(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_body(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_head(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_Fd(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_Fn(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_Nd(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_Nm(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_Sh(struct mpage *, const struct mdoc_node *);
+static int parse_mdoc_Xr(struct mpage *, const struct mdoc_node *);
+static void putkey(const struct mpage *,
+ const char *, uint64_t);
+static void putkeys(const struct mpage *,
+ const char *, size_t, uint64_t);
+static void putmdockey(const struct mpage *,
+ const struct mdoc_node *, uint64_t);
+static void say(const char *, const char *, ...);
+static int set_basedir(const char *);
+static int treescan(void);
+static size_t utf8(unsigned int, char [7]);
+static void utf8key(struct mchars *, struct str *);
+
+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 int exitcode; /* to be returned by main */
+static enum op op; /* operational mode */
+static char basedir[PATH_MAX]; /* current base directory */
+static struct ohash mpages; /* table of distinct manual pages */
+static struct ohash mlinks; /* table of directory entries */
+static struct ohash strings; /* table of all strings */
+static sqlite3 *db = NULL; /* current database */
+static sqlite3_stmt *stmts[STMT__MAX]; /* current statements */
+
+static const struct mdoc_handler mdocs[MDOC_MAX] = {
+ { NULL, 0 }, /* Ap */
+ { NULL, 0 }, /* Dd */
+ { NULL, 0 }, /* Dt */
+ { NULL, 0 }, /* Os */
+ { parse_mdoc_Sh, TYPE_Sh }, /* Sh */
+ { parse_mdoc_head, TYPE_Ss }, /* Ss */
+ { NULL, 0 }, /* Pp */
+ { NULL, 0 }, /* D1 */
+ { NULL, 0 }, /* Dl */
+ { NULL, 0 }, /* Bd */
+ { NULL, 0 }, /* Ed */
+ { NULL, 0 }, /* Bl */
+ { NULL, 0 }, /* El */
+ { NULL, 0 }, /* It */
+ { NULL, 0 }, /* Ad */
+ { NULL, TYPE_An }, /* An */
+ { NULL, TYPE_Ar }, /* Ar */
+ { NULL, TYPE_Cd }, /* Cd */
+ { NULL, TYPE_Cm }, /* Cm */
+ { NULL, TYPE_Dv }, /* Dv */
+ { NULL, TYPE_Er }, /* Er */
+ { NULL, TYPE_Ev }, /* Ev */
+ { NULL, 0 }, /* Ex */
+ { NULL, TYPE_Fa }, /* Fa */
+ { parse_mdoc_Fd, 0 }, /* Fd */
+ { NULL, TYPE_Fl }, /* Fl */
+ { parse_mdoc_Fn, 0 }, /* Fn */
+ { NULL, TYPE_Ft }, /* Ft */
+ { NULL, TYPE_Ic }, /* Ic */
+ { NULL, TYPE_In }, /* In */
+ { NULL, TYPE_Li }, /* Li */
+ { parse_mdoc_Nd, TYPE_Nd }, /* Nd */
+ { parse_mdoc_Nm, TYPE_Nm }, /* Nm */
+ { NULL, 0 }, /* Op */
+ { NULL, 0 }, /* Ot */
+ { NULL, TYPE_Pa }, /* Pa */
+ { NULL, 0 }, /* Rv */
+ { NULL, TYPE_St }, /* St */
+ { NULL, TYPE_Va }, /* Va */
+ { parse_mdoc_body, TYPE_Va }, /* Vt */
+ { parse_mdoc_Xr, 0 }, /* Xr */
+ { NULL, 0 }, /* %A */
+ { NULL, 0 }, /* %B */
+ { NULL, 0 }, /* %D */
+ { NULL, 0 }, /* %I */
+ { NULL, 0 }, /* %J */
+ { NULL, 0 }, /* %N */
+ { NULL, 0 }, /* %O */
+ { NULL, 0 }, /* %P */
+ { NULL, 0 }, /* %R */
+ { NULL, 0 }, /* %T */
+ { NULL, 0 }, /* %V */
+ { NULL, 0 }, /* Ac */
+ { NULL, 0 }, /* Ao */
+ { NULL, 0 }, /* Aq */
+ { NULL, TYPE_At }, /* At */
+ { NULL, 0 }, /* Bc */
+ { NULL, 0 }, /* Bf */
+ { NULL, 0 }, /* Bo */
+ { NULL, 0 }, /* Bq */
+ { NULL, TYPE_Bsx }, /* Bsx */
+ { NULL, TYPE_Bx }, /* Bx */
+ { NULL, 0 }, /* Db */
+ { NULL, 0 }, /* Dc */
+ { NULL, 0 }, /* Do */
+ { NULL, 0 }, /* Dq */
+ { NULL, 0 }, /* Ec */
+ { NULL, 0 }, /* Ef */
+ { NULL, TYPE_Em }, /* Em */
+ { NULL, 0 }, /* Eo */
+ { NULL, TYPE_Fx }, /* Fx */
+ { NULL, TYPE_Ms }, /* Ms */
+ { NULL, 0 }, /* No */
+ { NULL, 0 }, /* Ns */
+ { NULL, TYPE_Nx }, /* Nx */
+ { NULL, TYPE_Ox }, /* Ox */
+ { NULL, 0 }, /* Pc */
+ { NULL, 0 }, /* Pf */
+ { NULL, 0 }, /* Po */
+ { NULL, 0 }, /* Pq */
+ { NULL, 0 }, /* Qc */
+ { NULL, 0 }, /* Ql */
+ { NULL, 0 }, /* Qo */
+ { NULL, 0 }, /* Qq */
+ { NULL, 0 }, /* Re */
+ { NULL, 0 }, /* Rs */
+ { NULL, 0 }, /* Sc */
+ { NULL, 0 }, /* So */
+ { NULL, 0 }, /* Sq */
+ { NULL, 0 }, /* Sm */
+ { NULL, 0 }, /* Sx */
+ { NULL, TYPE_Sy }, /* Sy */
+ { NULL, TYPE_Tn }, /* Tn */
+ { NULL, 0 }, /* Ux */
+ { NULL, 0 }, /* Xc */
+ { NULL, 0 }, /* Xo */
+ { parse_mdoc_head, 0 }, /* Fo */
+ { NULL, 0 }, /* Fc */
+ { NULL, 0 }, /* Oo */
+ { NULL, 0 }, /* Oc */
+ { NULL, 0 }, /* Bk */
+ { NULL, 0 }, /* Ek */
+ { NULL, 0 }, /* Bt */
+ { NULL, 0 }, /* Hf */
+ { NULL, 0 }, /* Fr */
+ { NULL, 0 }, /* Ud */
+ { NULL, TYPE_Lb }, /* Lb */
+ { NULL, 0 }, /* Lp */
+ { NULL, TYPE_Lk }, /* Lk */
+ { NULL, TYPE_Mt }, /* Mt */
+ { NULL, 0 }, /* Brq */
+ { NULL, 0 }, /* Bro */
+ { NULL, 0 }, /* Brc */
+ { NULL, 0 }, /* %C */
+ { NULL, 0 }, /* Es */
+ { NULL, 0 }, /* En */
+ { NULL, TYPE_Dx }, /* Dx */
+ { NULL, 0 }, /* %Q */
+ { NULL, 0 }, /* br */
+ { NULL, 0 }, /* sp */
+ { NULL, 0 }, /* %U */
+ { NULL, 0 }, /* Ta */
+};