+static int macro_obsolete(MACRO_PROT_ARGS);
+static int macro_constant(MACRO_PROT_ARGS);
+static int macro_constant_scoped(MACRO_PROT_ARGS);
+static int macro_constant_delimited(MACRO_PROT_ARGS);
+static int macro_text(MACRO_PROT_ARGS);
+static int macro_scoped(MACRO_PROT_ARGS);
+static int macro_scoped_close(MACRO_PROT_ARGS);
+static int macro_scoped_line(MACRO_PROT_ARGS);
+
+#define REWIND_REWIND (1 << 0)
+#define REWIND_NOHALT (1 << 1)
+#define REWIND_HALT (1 << 2)
+
+static int rewind_dohalt(int, enum mdoc_type,
+ const struct mdoc_node *);
+static int rewind_alt(int);
+static int rewind_dobreak(int, const struct mdoc_node *);
+static int rewind_elem(struct mdoc *, int);
+static int rewind_impblock(struct mdoc *, int, int, int);
+static int rewind_expblock(struct mdoc *, int, int, int);
+static int rewind_subblock(enum mdoc_type,
+ struct mdoc *, int, int, int);
+static int rewind_last(struct mdoc *, struct mdoc_node *);
+static int append_delims(struct mdoc *, int, int *, char *);
+static int lookup(struct mdoc *, int, int, int, const char *);
+static int pwarn(struct mdoc *, int, int, int);
+static int perr(struct mdoc *, int, int, int);
+
+#define WMACPARM (1)
+#define WOBS (2)
+
+#define ENOCTX (1)
+#define ENOPARMS (2)
+#define EARGVLIM (3)
+
+/* Central table of library: who gets parsed how. */
+
+const struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
+ { NULL, 0 }, /* \" */
+ { macro_constant, MDOC_PROLOGUE }, /* Dd */
+ { macro_constant, MDOC_PROLOGUE }, /* Dt */
+ { macro_constant, MDOC_PROLOGUE }, /* Os */
+ { macro_scoped, 0 }, /* Sh */
+ { macro_scoped, 0 }, /* Ss */
+ { macro_text, 0 }, /* Pp */
+ { macro_scoped_line, MDOC_PARSED }, /* D1 */
+ { macro_scoped_line, MDOC_PARSED }, /* Dl */
+ { macro_scoped, MDOC_EXPLICIT }, /* Bd */
+ { macro_scoped_close, MDOC_EXPLICIT }, /* Ed */
+ { macro_scoped, MDOC_EXPLICIT }, /* Bl */
+ { macro_scoped_close, MDOC_EXPLICIT }, /* El */
+ { macro_scoped, MDOC_PARSED }, /* It */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
+ { macro_text, MDOC_PARSED }, /* An */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
+ { macro_constant, 0 }, /* Cd */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
+ { macro_constant, 0 }, /* Ex */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
+ { macro_constant, 0 }, /* Fd */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
+ { macro_text, MDOC_PARSED }, /* Ft */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
+ { macro_constant, 0 }, /* In */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
+ { macro_constant, 0 }, /* Nd */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
+ { macro_obsolete, 0 }, /* Ot */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
+ { macro_constant, 0 }, /* Rv */
+ /* XXX - .St supposed to be (but isn't) callable. */
+ { macro_constant_delimited, MDOC_PARSED }, /* St */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
+ { macro_constant, 0 }, /* %A */
+ { macro_constant, 0 }, /* %B */
+ { macro_constant, 0 }, /* %D */
+ { macro_constant, 0 }, /* %I */
+ { macro_constant, 0 }, /* %J */
+ { macro_constant, 0 }, /* %N */
+ { macro_constant, 0 }, /* %O */
+ { macro_constant, 0 }, /* %P */
+ { macro_constant, 0 }, /* %R */
+ { macro_constant, 0 }, /* %T */
+ { macro_constant, 0 }, /* %V */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
+ { macro_constant_delimited, 0 }, /* At */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
+ { macro_scoped, MDOC_EXPLICIT }, /* Bf */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
+ { macro_constant_delimited, MDOC_PARSED }, /* Bsx */
+ { macro_constant_delimited, MDOC_PARSED }, /* Bx */
+ { macro_constant, 0 }, /* Db */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
+ { macro_scoped_close, MDOC_EXPLICIT }, /* Ef */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Em */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
+ { macro_constant_delimited, MDOC_PARSED }, /* Fx */
+ { macro_text, MDOC_PARSED }, /* Ms */
+ { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* No */
+ { macro_constant_delimited, MDOC_CALLABLE | MDOC_PARSED }, /* Ns */
+ { macro_constant_delimited, MDOC_PARSED }, /* Nx */
+ { macro_constant_delimited, MDOC_PARSED }, /* Ox */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
+ { macro_constant_delimited, MDOC_PARSED }, /* Pf */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
+ { macro_scoped_close, MDOC_EXPLICIT }, /* Re */
+ { macro_scoped, MDOC_EXPLICIT }, /* Rs */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
+ { macro_scoped_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
+ { macro_constant, 0 }, /* Sm */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
+ { macro_text, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
+ { macro_constant_delimited, MDOC_PARSED }, /* Ux */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
+ /* XXX - .Fo supposed to be (but isn't) callable. */
+ { macro_scoped, MDOC_EXPLICIT }, /* Fo */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */
+ { macro_constant_scoped, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
+ { macro_scoped_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
+ { macro_scoped, MDOC_EXPLICIT }, /* Bk */
+ { macro_scoped_close, MDOC_EXPLICIT }, /* Ek */
+ { macro_constant, 0 }, /* Bt */
+ { macro_constant, 0 }, /* Hf */
+ { macro_obsolete, 0 }, /* Fr */
+ { macro_constant, 0 }, /* Ud */
+ { macro_constant, 0 }, /* Lb */
+};
+
+const struct mdoc_macro * const mdoc_macros = __mdoc_macros;