source@mandoc.bsd.lv
 help / color / mirror / Atom feed
* mdocml: Continue parser unification: * Make enum rofft an internal
@ 2017-04-24 23:06 schwarze
  0 siblings, 0 replies; only message in thread
From: schwarze @ 2017-04-24 23:06 UTC (permalink / raw)
  To: source

Log Message:
-----------
Continue parser unification:
* Make enum rofft an internal interface as enum roff_tok in "roff.h".
* Represent mdoc and man macros in enum roff_tok.
* Make TOKEN_NONE a proper enum value and use it throughout.
* Put the prologue macros first in the macro tables.
* Unify mdoc_macroname[] and man_macroname[] into roff_name[].

Modified Files:
--------------
    mdocml:
        libman.h
        libmdoc.h
        man.c
        man.h
        man_hash.c
        man_html.c
        man_macro.c
        man_term.c
        man_validate.c
        mandoc_headers.3
        mandocdb.c
        mdoc.c
        mdoc.h
        mdoc_argv.c
        mdoc_hash.c
        mdoc_html.c
        mdoc_macro.c
        mdoc_man.c
        mdoc_markdown.c
        mdoc_state.c
        mdoc_term.c
        mdoc_validate.c
        roff.c
        roff.h
        tree.c

Revision Data
-------------
Index: mdoc_term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_term.c,v
retrieving revision 1.349
retrieving revision 1.350
diff -Lmdoc_term.c -Lmdoc_term.c -u -p -r1.349 -r1.350
--- mdoc_term.c
+++ mdoc_term.c
@@ -125,8 +125,7 @@ static	int	  termp_vt_pre(DECL_ARGS);
 static	int	  termp_xr_pre(DECL_ARGS);
 static	int	  termp_xx_pre(DECL_ARGS);
 
-static	const struct termact termacts[MDOC_MAX] = {
-	{ termp_ap_pre, NULL }, /* Ap */
+static	const struct termact __termacts[MDOC_MAX - MDOC_Dd] = {
 	{ NULL, NULL }, /* Dd */
 	{ NULL, NULL }, /* Dt */
 	{ NULL, NULL }, /* Os */
@@ -142,6 +141,7 @@ static	const struct termact termacts[MDO
 	{ termp_it_pre, termp_it_post }, /* It */
 	{ termp_under_pre, NULL }, /* Ad */
 	{ termp_an_pre, NULL }, /* An */
+	{ termp_ap_pre, NULL }, /* Ap */
 	{ termp_under_pre, NULL }, /* Ar */
 	{ termp_cd_pre, NULL }, /* Cd */
 	{ termp_bold_pre, NULL }, /* Cm */
@@ -250,9 +250,11 @@ static	const struct termact termacts[MDO
 	{ NULL, NULL }, /* Ta */
 	{ termp_ll_pre, NULL }, /* ll */
 };
+static	const struct termact *const termacts = __termacts - MDOC_Dd;
 
 static	int	 fn_prio;
 
+
 void
 terminal_mdoc(void *arg, const struct roff_man *mdoc)
 {
@@ -363,7 +365,7 @@ print_mdoc_node(DECL_ARGS)
 		term_tbl(p, n->span);
 		break;
 	default:
-		if (termacts[n->tok].pre &&
+		if (termacts[n->tok].pre != NULL &&
 		    (n->end == ENDBODY_NOT || n->child != NULL))
 			chld = (*termacts[n->tok].pre)
 				(p, &npair, meta, n);
@@ -384,7 +386,7 @@ print_mdoc_node(DECL_ARGS)
 	case ROFFT_EQN:
 		break;
 	default:
-		if ( ! termacts[n->tok].post || NODE_ENDED & n->flags)
+		if (termacts[n->tok].post == NULL || n->flags & NODE_ENDED)
 			break;
 		(void)(*termacts[n->tok].post)(p, &npair, meta, n);
 
Index: mdoc_validate.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_validate.c,v
retrieving revision 1.319
retrieving revision 1.320
diff -Lmdoc_validate.c -Lmdoc_validate.c -u -p -r1.319 -r1.320
--- mdoc_validate.c
+++ mdoc_validate.c
@@ -57,7 +57,7 @@ static	void	 check_argv(struct roff_man 
 			struct roff_node *, struct mdoc_argv *);
 static	void	 check_args(struct roff_man *, struct roff_node *);
 static	int	 child_an(const struct roff_node *);
-static	size_t		macro2len(int);
+static	size_t		macro2len(enum roff_tok);
 static	void	 rewrite_macro2len(char **);
 
 static	void	 post_an(POST_ARGS);
@@ -108,8 +108,7 @@ static	void	 post_std(POST_ARGS);
 static	void	 post_xr(POST_ARGS);
 static	void	 post_xx(POST_ARGS);
 
-static	v_post mdoc_valids[MDOC_MAX] = {
-	NULL,		/* Ap */
+static	const v_post __mdoc_valids[MDOC_MAX - MDOC_Dd] = {
 	post_dd,	/* Dd */
 	post_dt,	/* Dt */
 	post_os,	/* Os */
@@ -125,6 +124,7 @@ static	v_post mdoc_valids[MDOC_MAX] = {
 	post_it,	/* It */
 	NULL,		/* Ad */
 	post_an,	/* An */
+	NULL,		/* Ap */
 	post_defaults,	/* Ar */
 	NULL,		/* Cd */
 	NULL,		/* Cm */
@@ -233,10 +233,11 @@ static	v_post mdoc_valids[MDOC_MAX] = {
 	NULL,		/* Ta */
 	NULL,		/* ll */
 };
+static	const v_post *const mdoc_valids = __mdoc_valids - MDOC_Dd;
 
 #define	RSORD_MAX 14 /* Number of `Rs' blocks. */
 
-static	const int rsord[RSORD_MAX] = {
+static	const enum roff_tok rsord[RSORD_MAX] = {
 	MDOC__A,
 	MDOC__T,
 	MDOC__B,
@@ -284,7 +285,7 @@ void
 mdoc_node_validate(struct roff_man *mdoc)
 {
 	struct roff_node *n;
-	v_post *p;
+	const v_post *p;
 
 	n = mdoc->last;
 	mdoc->last = mdoc->last->child;
@@ -661,9 +662,8 @@ post_eoln(POST_ARGS)
 
 	n = mdoc->last;
 	if (n->child != NULL)
-		mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
-		    n->line, n->pos, "%s %s",
-		    mdoc_macronames[n->tok], n->child->string);
+		mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, n->line,
+		    n->pos, "%s %s", roff_name[n->tok], n->child->string);
 
 	while (n->child != NULL)
 		roff_node_delete(mdoc, n->child);
@@ -817,7 +817,7 @@ post_std(POST_ARGS)
 			return;
 
 	mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse,
-	    n->line, n->pos, mdoc_macronames[n->tok]);
+	    n->line, n->pos, roff_name[n->tok]);
 }
 
 static void
@@ -852,7 +852,7 @@ post_obsolete(POST_ARGS)
 	n = mdoc->last;
 	if (n->type == ROFFT_ELEM || n->type == ROFFT_BLOCK)
 		mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse,
-		    n->line, n->pos, mdoc_macronames[n->tok]);
+		    n->line, n->pos, roff_name[n->tok]);
 }
 
 /*
@@ -1060,7 +1060,7 @@ post_display(POST_ARGS)
 				roff_node_delete(mdoc, n);
 		} else if (n->child == NULL)
 			mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse,
-			    n->line, n->pos, mdoc_macronames[n->tok]);
+			    n->line, n->pos, roff_name[n->tok]);
 		else if (n->tok == MDOC_D1)
 			post_hyph(mdoc);
 		break;
@@ -1083,7 +1083,7 @@ post_display(POST_ARGS)
 			if (np->type == ROFFT_BLOCK && np->tok == MDOC_Bd) {
 				mandoc_vmsg(MANDOCERR_BD_NEST,
 				    mdoc->parse, n->line, n->pos,
-				    "%s in Bd", mdoc_macronames[n->tok]);
+				    "%s in Bd", roff_name[n->tok]);
 				break;
 			}
 		}
@@ -1269,10 +1269,10 @@ post_it(POST_ARGS)
 		/* FALLTHROUGH */
 	case LIST_item:
 		if ((nch = nit->head->child) != NULL)
-			mandoc_vmsg(MANDOCERR_ARG_SKIP,
-			    mdoc->parse, nit->line, nit->pos,
-			    "It %s", nch->string == NULL ?
-			    mdoc_macronames[nch->tok] : nch->string);
+			mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse,
+			    nit->line, nit->pos, "It %s",
+			    nch->string == NULL ? roff_name[nch->tok] :
+			    nch->string);
 		break;
 	case LIST_column:
 		cols = (int)nbl->norm->Bl.ncols;
@@ -1319,14 +1319,13 @@ post_bl_block(POST_ARGS)
 			if (ni->next == NULL) {
 				mandoc_msg(MANDOCERR_PAR_MOVE,
 				    mdoc->parse, nc->line, nc->pos,
-				    mdoc_macronames[nc->tok]);
+				    roff_name[nc->tok]);
 				mdoc_node_relink(mdoc, nc);
 			} else if (n->norm->Bl.comp == 0 &&
 			    n->norm->Bl.type != LIST_column) {
 				mandoc_vmsg(MANDOCERR_PAR_SKIP,
 				    mdoc->parse, nc->line, nc->pos,
-				    "%s before It",
-				    mdoc_macronames[nc->tok]);
+				    "%s before It", roff_name[nc->tok]);
 				roff_node_delete(mdoc, nc);
 			} else
 				break;
@@ -1343,7 +1342,7 @@ void
 rewrite_macro2len(char **arg)
 {
 	size_t		  width;
-	int		  tok;
+	enum roff_tok	  tok;
 
 	if (*arg == NULL)
 		return;
@@ -1490,8 +1489,7 @@ post_bl(POST_ARGS)
 		}
 
 		mandoc_msg(MANDOCERR_BL_MOVE, mdoc->parse,
-		    nchild->line, nchild->pos,
-		    mdoc_macronames[nchild->tok]);
+		    nchild->line, nchild->pos, roff_name[nchild->tok]);
 
 		/*
 		 * Move the node out of the Bl block.
@@ -1569,7 +1567,7 @@ post_sm(POST_ARGS)
 
 	mandoc_vmsg(MANDOCERR_SM_BAD,
 	    mdoc->parse, nch->line, nch->pos,
-	    "%s %s", mdoc_macronames[mdoc->last->tok], nch->string);
+	    "%s %s", roff_name[mdoc->last->tok], nch->string);
 	mdoc_node_relink(mdoc, nch);
 	return;
 }
@@ -1612,7 +1610,7 @@ post_root(POST_ARGS)
 		mandoc_msg(MANDOCERR_DOC_EMPTY, mdoc->parse, 0, 0, NULL);
 	else if (n->tok != MDOC_Sh)
 		mandoc_msg(MANDOCERR_SEC_BEFORE, mdoc->parse,
-		    n->line, n->pos, mdoc_macronames[n->tok]);
+		    n->line, n->pos, roff_name[n->tok]);
 }
 
 static void
@@ -1646,9 +1644,8 @@ post_rs(POST_ARGS)
 				break;
 
 		if (i == RSORD_MAX) {
-			mandoc_msg(MANDOCERR_RS_BAD,
-			    mdoc->parse, nch->line, nch->pos,
-			    mdoc_macronames[nch->tok]);
+			mandoc_msg(MANDOCERR_RS_BAD, mdoc->parse,
+			    nch->line, nch->pos, roff_name[nch->tok]);
 			i = -1;
 		} else if (nch->tok == MDOC__J || nch->tok == MDOC__B)
 			np->norm->Rs.quote_T++;
@@ -1801,7 +1798,7 @@ post_sh_name(POST_ARGS)
 			/* FALLTHROUGH */
 		default:
 			mandoc_msg(MANDOCERR_NAMESEC_BAD, mdoc->parse,
-			    n->line, n->pos, mdoc_macronames[n->tok]);
+			    n->line, n->pos, roff_name[n->tok]);
 			continue;
 		}
 		break;
@@ -1922,7 +1919,7 @@ post_sh_head(POST_ARGS)
 		    sec != SEC_CUSTOM ? secnames[sec] :
 		    (nch = mdoc->last->child) == NULL ? "" :
 		    nch->type == ROFFT_TEXT ? nch->string :
-		    mdoc_macronames[nch->tok]);
+		    roff_name[nch->tok]);
 
 	/* The SYNOPSIS gets special attention in other areas. */
 
@@ -2031,8 +2028,8 @@ post_ignpar(POST_ARGS)
 		if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {
 			mandoc_vmsg(MANDOCERR_PAR_SKIP,
 			    mdoc->parse, np->line, np->pos,
-			    "%s after %s", mdoc_macronames[np->tok],
-			    mdoc_macronames[mdoc->last->tok]);
+			    "%s after %s", roff_name[np->tok],
+			    roff_name[mdoc->last->tok]);
 			roff_node_delete(mdoc, np);
 		}
 
@@ -2040,8 +2037,8 @@ post_ignpar(POST_ARGS)
 		if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) {
 			mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
 			    np->line, np->pos, "%s at the end of %s",
-			    mdoc_macronames[np->tok],
-			    mdoc_macronames[mdoc->last->tok]);
+			    roff_name[np->tok],
+			    roff_name[mdoc->last->tok]);
 			roff_node_delete(mdoc, np);
 		}
 }
@@ -2074,9 +2071,8 @@ post_prevpar(POST_ARGS)
 		return;
 
 	mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
-	    n->prev->line, n->prev->pos,
-	    "%s before %s", mdoc_macronames[n->prev->tok],
-	    mdoc_macronames[n->tok]);
+	    n->prev->line, n->prev->pos, "%s before %s",
+	    roff_name[n->prev->tok], roff_name[n->tok]);
 	roff_node_delete(mdoc, n->prev);
 }
 
@@ -2097,7 +2093,7 @@ post_par(POST_ARGS)
 	} else if (np->child != NULL)
 		mandoc_vmsg(MANDOCERR_ARG_SKIP,
 		    mdoc->parse, np->line, np->pos, "%s %s",
-		    mdoc_macronames[np->tok], np->child->string);
+		    roff_name[np->tok], np->child->string);
 
 	if ((np = mdoc->last->prev) == NULL) {
 		np = mdoc->last->parent;
@@ -2109,9 +2105,8 @@ post_par(POST_ARGS)
 		return;
 
 	mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse,
-	    mdoc->last->line, mdoc->last->pos,
-	    "%s after %s", mdoc_macronames[mdoc->last->tok],
-	    mdoc_macronames[np->tok]);
+	    mdoc->last->line, mdoc->last->pos, "%s after %s",
+	    roff_name[mdoc->last->tok], roff_name[np->tok]);
 	roff_node_delete(mdoc, mdoc->last);
 }
 
@@ -2362,7 +2357,7 @@ mdoc_a2sec(const char *p)
 }
 
 static size_t
-macro2len(int macro)
+macro2len(enum roff_tok macro)
 {
 
 	switch (macro) {
Index: man_validate.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man_validate.c,v
retrieving revision 1.122
retrieving revision 1.123
diff -Lman_validate.c -Lman_validate.c -u -p -r1.122 -r1.123
--- man_validate.c
+++ man_validate.c
@@ -1,7 +1,7 @@
 /*	$OpenBSD$ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012-2017 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -54,8 +54,7 @@ static	void	  post_TH(CHKARGS);
 static	void	  post_UC(CHKARGS);
 static	void	  post_UR(CHKARGS);
 
-static	v_check man_valids[MAN_MAX] = {
-	post_vs,    /* br */
+static	const v_check __man_valids[MAN_MAX - MAN_TH] = {
 	post_TH,    /* TH */
 	NULL,       /* SH */
 	NULL,       /* SS */
@@ -76,6 +75,7 @@ static	v_check man_valids[MAN_MAX] = {
 	NULL,       /* I */
 	NULL,       /* IR */
 	NULL,       /* RI */
+	post_vs,    /* br */
 	post_vs,    /* sp */
 	NULL,       /* nf */
 	NULL,       /* fi */
@@ -94,13 +94,14 @@ static	v_check man_valids[MAN_MAX] = {
 	NULL,       /* UE */
 	NULL,       /* ll */
 };
+static	const v_check *man_valids = __man_valids - MAN_TH;
 
 
 void
 man_node_validate(struct roff_man *man)
 {
 	struct roff_node *n;
-	v_check		*cp;
+	const v_check	 *cp;
 
 	n = man->last;
 	man->last = man->last->child;
@@ -247,7 +248,7 @@ check_part(CHKARGS)
 
 	if (n->type == ROFFT_BODY && n->child == NULL)
 		mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse,
-		    n->line, n->pos, man_macronames[n->tok]);
+		    n->line, n->pos, roff_name[n->tok]);
 }
 
 static void
@@ -263,14 +264,13 @@ check_par(CHKARGS)
 		if (n->child == NULL)
 			mandoc_vmsg(MANDOCERR_PAR_SKIP,
 			    man->parse, n->line, n->pos,
-			    "%s empty", man_macronames[n->tok]);
+			    "%s empty", roff_name[n->tok]);
 		break;
 	case ROFFT_HEAD:
 		if (n->child != NULL)
 			mandoc_vmsg(MANDOCERR_ARG_SKIP,
-			    man->parse, n->line, n->pos,
-			    "%s %s%s", man_macronames[n->tok],
-			    n->child->string,
+			    man->parse, n->line, n->pos, "%s %s%s",
+			    roff_name[n->tok], n->child->string,
 			    n->child->next != NULL ? " ..." : "");
 		break;
 	default:
@@ -291,7 +291,7 @@ post_IP(CHKARGS)
 		if (n->parent->head->child == NULL && n->child == NULL)
 			mandoc_vmsg(MANDOCERR_PAR_SKIP,
 			    man->parse, n->line, n->pos,
-			    "%s empty", man_macronames[n->tok]);
+			    "%s empty", roff_name[n->tok]);
 		break;
 	default:
 		break;
@@ -479,8 +479,8 @@ post_vs(CHKARGS)
 	case MAN_SH:
 	case MAN_SS:
 		mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos,
-		    "%s after %s", man_macronames[n->tok],
-		    man_macronames[n->parent->tok]);
+		    "%s after %s", roff_name[n->tok],
+		    roff_name[n->parent->tok]);
 		/* FALLTHROUGH */
 	case TOKEN_NONE:
 		/*
Index: mdoc_argv.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_argv.c,v
retrieving revision 1.110
retrieving revision 1.111
diff -Lmdoc_argv.c -Lmdoc_argv.c -u -p -r1.110 -r1.111
--- mdoc_argv.c
+++ mdoc_argv.c
@@ -144,8 +144,7 @@ static	const enum mdocargt args_Bl[] = {
 	MDOC_ARG_MAX
 };
 
-static	const struct mdocarg mdocargs[MDOC_MAX] = {
-	{ ARGSFL_DELIM, NULL }, /* Ap */
+static	const struct mdocarg __mdocargs[MDOC_MAX - MDOC_Dd] = {
 	{ ARGSFL_NONE, NULL }, /* Dd */
 	{ ARGSFL_NONE, NULL }, /* Dt */
 	{ ARGSFL_NONE, NULL }, /* Os */
@@ -161,6 +160,7 @@ static	const struct mdocarg mdocargs[MDO
 	{ ARGSFL_NONE, NULL }, /* It */
 	{ ARGSFL_DELIM, NULL }, /* Ad */
 	{ ARGSFL_DELIM, args_An }, /* An */
+	{ ARGSFL_DELIM, NULL }, /* Ap */
 	{ ARGSFL_DELIM, NULL }, /* Ar */
 	{ ARGSFL_DELIM, NULL }, /* Cd */
 	{ ARGSFL_DELIM, NULL }, /* Cm */
@@ -269,6 +269,7 @@ static	const struct mdocarg mdocargs[MDO
 	{ ARGSFL_NONE, NULL }, /* Ta */
 	{ ARGSFL_NONE, NULL }, /* ll */
 };
+static	const struct mdocarg *const mdocargs = __mdocargs - MDOC_Dd;
 
 
 /*
@@ -277,7 +278,7 @@ static	const struct mdocarg mdocargs[MDO
  * Some flags take no argument, some one, some multiple.
  */
 void
-mdoc_argv(struct roff_man *mdoc, int line, int tok,
+mdoc_argv(struct roff_man *mdoc, int line, enum roff_tok tok,
 	struct mdoc_arg **reta, int *pos, char *buf)
 {
 	struct mdoc_argv	  tmpv;
@@ -291,6 +292,7 @@ mdoc_argv(struct roff_man *mdoc, int lin
 
 	/* Which flags does this macro support? */
 
+	assert(tok >= MDOC_Dd && tok < MDOC_MAX);
 	argtable = mdocargs[tok].argvs;
 	if (argtable == NULL)
 		return;
@@ -415,7 +417,7 @@ argn_free(struct mdoc_arg *p, int iarg)
 
 enum margserr
 mdoc_args(struct roff_man *mdoc, int line, int *pos,
-	char *buf, int tok, char **v)
+	char *buf, enum roff_tok tok, char **v)
 {
 	struct roff_node *n;
 	char		 *v_local;
Index: roff.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.c,v
retrieving revision 1.293
retrieving revision 1.294
diff -Lroff.c -Lroff.c -u -p -r1.293 -r1.294
--- roff.c
+++ roff.c
@@ -38,253 +38,6 @@
 
 /* --- data types --------------------------------------------------------- */
 
-enum	rofft {
-	ROFF_ab,
-	ROFF_ad,
-	ROFF_af,
-	ROFF_aln,
-	ROFF_als,
-	ROFF_am,
-	ROFF_am1,
-	ROFF_ami,
-	ROFF_ami1,
-	ROFF_as,
-	ROFF_as1,
-	ROFF_asciify,
-	ROFF_backtrace,
-	ROFF_bd,
-	ROFF_bleedat,
-	ROFF_blm,
-	ROFF_box,
-	ROFF_boxa,
-	ROFF_bp,
-	ROFF_BP,
-	/* MAN_br, MDOC_br */
-	ROFF_break,
-	ROFF_breakchar,
-	ROFF_brnl,
-	ROFF_brp,
-	ROFF_brpnl,
-	ROFF_c2,
-	ROFF_cc,
-	ROFF_ce,
-	ROFF_cf,
-	ROFF_cflags,
-	ROFF_ch,
-	ROFF_char,
-	ROFF_chop,
-	ROFF_class,
-	ROFF_close,
-	ROFF_CL,
-	ROFF_color,
-	ROFF_composite,
-	ROFF_continue,
-	ROFF_cp,
-	ROFF_cropat,
-	ROFF_cs,
-	ROFF_cu,
-	ROFF_da,
-	ROFF_dch,
-	ROFF_Dd,
-	ROFF_de,
-	ROFF_de1,
-	ROFF_defcolor,
-	ROFF_dei,
-	ROFF_dei1,
-	ROFF_device,
-	ROFF_devicem,
-	ROFF_di,
-	ROFF_do,
-	ROFF_ds,
-	ROFF_ds1,
-	ROFF_dwh,
-	ROFF_dt,
-	ROFF_ec,
-	ROFF_ecr,
-	ROFF_ecs,
-	ROFF_el,
-	ROFF_em,
-	ROFF_EN,
-	ROFF_eo,
-	ROFF_EP,
-	ROFF_EQ,
-	ROFF_errprint,
-	ROFF_ev,
-	ROFF_evc,
-	ROFF_ex,
-	ROFF_fallback,
-	ROFF_fam,
-	ROFF_fc,
-	ROFF_fchar,
-	ROFF_fcolor,
-	ROFF_fdeferlig,
-	ROFF_feature,
-	/* MAN_fi; ignored in mdoc(7) */
-	ROFF_fkern,
-	ROFF_fl,
-	ROFF_flig,
-	ROFF_fp,
-	ROFF_fps,
-	ROFF_fschar,
-	ROFF_fspacewidth,
-	ROFF_fspecial,
-	/* MAN_ft; ignored in mdoc(7) */
-	ROFF_ftr,
-	ROFF_fzoom,
-	ROFF_gcolor,
-	ROFF_hc,
-	ROFF_hcode,
-	ROFF_hidechar,
-	ROFF_hla,
-	ROFF_hlm,
-	ROFF_hpf,
-	ROFF_hpfa,
-	ROFF_hpfcode,
-	ROFF_hw,
-	ROFF_hy,
-	ROFF_hylang,
-	ROFF_hylen,
-	ROFF_hym,
-	ROFF_hypp,
-	ROFF_hys,
-	ROFF_ie,
-	ROFF_if,
-	ROFF_ig,
-	/* MAN_in; ignored in mdoc(7) */
-	ROFF_index,
-	ROFF_it,
-	ROFF_itc,
-	ROFF_IX,
-	ROFF_kern,
-	ROFF_kernafter,
-	ROFF_kernbefore,
-	ROFF_kernpair,
-	ROFF_lc,
-	ROFF_lc_ctype,
-	ROFF_lds,
-	ROFF_length,
-	ROFF_letadj,
-	ROFF_lf,
-	ROFF_lg,
-	ROFF_lhang,
-	ROFF_linetabs,
-	/* MAN_ll, MDOC_ll */
-	ROFF_lnr,
-	ROFF_lnrf,
-	ROFF_lpfx,
-	ROFF_ls,
-	ROFF_lsm,
-	ROFF_lt,
-	ROFF_mc,
-	ROFF_mediasize,
-	ROFF_minss,
-	ROFF_mk,
-	ROFF_mso,
-	ROFF_na,
-	ROFF_ne,
-	/* MAN_nf; ignored in mdoc(7) */
-	ROFF_nh,
-	ROFF_nhychar,
-	ROFF_nm,
-	ROFF_nn,
-	ROFF_nop,
-	ROFF_nr,
-	ROFF_nrf,
-	ROFF_nroff,
-	ROFF_ns,
-	ROFF_nx,
-	ROFF_open,
-	ROFF_opena,
-	ROFF_os,
-	ROFF_output,
-	ROFF_padj,
-	ROFF_papersize,
-	ROFF_pc,
-	ROFF_pev,
-	ROFF_pi,
-	ROFF_PI,
-	ROFF_pl,
-	ROFF_pm,
-	ROFF_pn,
-	ROFF_pnr,
-	ROFF_po,
-	ROFF_ps,
-	ROFF_psbb,
-	ROFF_pshape,
-	ROFF_pso,
-	ROFF_ptr,
-	ROFF_pvs,
-	ROFF_rchar,
-	ROFF_rd,
-	ROFF_recursionlimit,
-	ROFF_return,
-	ROFF_rfschar,
-	ROFF_rhang,
-	ROFF_rj,
-	ROFF_rm,
-	ROFF_rn,
-	ROFF_rnn,
-	ROFF_rr,
-	ROFF_rs,
-	ROFF_rt,
-	ROFF_schar,
-	ROFF_sentchar,
-	ROFF_shc,
-	ROFF_shift,
-	ROFF_sizes,
-	ROFF_so,
-	/* MAN_sp, MDOC_sp */
-	ROFF_spacewidth,
-	ROFF_special,
-	ROFF_spreadwarn,
-	ROFF_ss,
-	ROFF_sty,
-	ROFF_substring,
-	ROFF_sv,
-	ROFF_sy,
-	ROFF_T_,
-	ROFF_ta,
-	ROFF_tc,
-	ROFF_TE,
-	ROFF_TH,
-	ROFF_ti,
-	ROFF_tkf,
-	ROFF_tl,
-	ROFF_tm,
-	ROFF_tm1,
-	ROFF_tmc,
-	ROFF_tr,
-	ROFF_track,
-	ROFF_transchar,
-	ROFF_trf,
-	ROFF_trimat,
-	ROFF_trin,
-	ROFF_trnt,
-	ROFF_troff,
-	ROFF_TS,
-	ROFF_uf,
-	ROFF_ul,
-	ROFF_unformat,
-	ROFF_unwatch,
-	ROFF_unwatchn,
-	ROFF_vpt,
-	ROFF_vs,
-	ROFF_warn,
-	ROFF_warnscale,
-	ROFF_watch,
-	ROFF_watchlength,
-	ROFF_watchn,
-	ROFF_wh,
-	ROFF_while,
-	ROFF_write,
-	ROFF_writec,
-	ROFF_writem,
-	ROFF_xflag,
-	ROFF_cblock,
-	ROFF_USERDEF,
-	ROFF_MAX
-};
-
 /*
  * An incredibly-simple string buffer.
  */
@@ -336,7 +89,7 @@ struct	roff {
 };
 
 struct	roffnode {
-	enum rofft	 tok; /* type of node */
+	enum roff_tok	 tok; /* type of node */
 	struct roffnode	*parent; /* up one in stack */
 	int		 line; /* parse line */
 	int		 col; /* parse col */
@@ -347,7 +100,7 @@ struct	roffnode {
 };
 
 #define	ROFF_ARGS	 struct roff *r, /* parse ctx */ \
-			 enum rofft tok, /* tok of macro */ \
+			 enum roff_tok tok, /* tok of macro */ \
 			 struct buf *buf, /* input buffer */ \
 			 int ln, /* parse line */ \
 			 int ppos, /* original pos in buffer */ \
@@ -376,11 +129,11 @@ struct	predef {
 
 /* --- function prototypes ------------------------------------------------ */
 
-static	enum rofft	 roffhash_find(const char *, size_t);
+static	enum roff_tok	 roffhash_find(const char *, size_t);
 static	void		 roffhash_init(void);
 static	void		 roffnode_cleanscope(struct roff *);
 static	void		 roffnode_pop(struct roff *);
-static	void		 roffnode_push(struct roff *, enum rofft,
+static	void		 roffnode_push(struct roff *, enum roff_tok,
 				const char *, int, int);
 static	enum rofferr	 roff_block(ROFF_ARGS);
 static	enum rofferr	 roff_block_text(ROFF_ARGS);
@@ -420,7 +173,7 @@ static	enum rofferr	 roff_line_ignore(RO
 static	void		 roff_man_alloc1(struct roff_man *);
 static	void		 roff_man_free1(struct roff_man *);
 static	enum rofferr	 roff_nr(ROFF_ARGS);
-static	enum rofft	 roff_parse(struct roff *, char *, int *,
+static	enum roff_tok	 roff_parse(struct roff *, char *, int *,
 				int, int);
 static	enum rofferr	 roff_parsetext(struct buf *, int, int *);
 static	enum rofferr	 roff_res(struct roff *, struct buf *, int, int);
@@ -453,9 +206,114 @@ static	enum rofferr	 roff_userdef(ROFF_A
 #define	ROFFNUM_SCALE	(1 << 0)  /* Honour scaling in roff_getnum(). */
 #define	ROFFNUM_WHITE	(1 << 1)  /* Skip whitespace in roff_evalnum(). */
 
+const char *__roff_name[MAN_MAX + 1] = {
+	"ab",		"ad",		"af",		"aln",
+	"als",		"am",		"am1",		"ami",
+	"ami1",		"as",		"as1",		"asciify",
+	"backtrace",	"bd",		"bleedat",	"blm",
+        "box",		"boxa",		"bp",		"BP",
+	"break",	"breakchar",	"brnl",		"brp",
+	"brpnl",	"c2",		"cc",		"ce",
+	"cf",		"cflags",	"ch",		"char",
+	"chop",		"class",	"close",	"CL",
+	"color",	"composite",	"continue",	"cp",
+	"cropat",	"cs",		"cu",		"da",
+	"dch",		"Dd",		"de",		"de1",
+	"defcolor",	"dei",		"dei1",		"device",
+	"devicem",	"di",		"do",		"ds",
+	"ds1",		"dwh",		"dt",		"ec",
+	"ecr",		"ecs",		"el",		"em",
+	"EN",		"eo",		"EP",		"EQ",
+	"errprint",	"ev",		"evc",		"ex",
+	"fallback",	"fam",		"fc",		"fchar",
+	"fcolor",	"fdeferlig",	"feature",	"fkern",
+	"fl",		"flig",		"fp",		"fps",
+	"fschar",	"fspacewidth",	"fspecial",	"ftr",
+	"fzoom",	"gcolor",	"hc",		"hcode",
+	"hidechar",	"hla",		"hlm",		"hpf",
+	"hpfa",		"hpfcode",	"hw",		"hy",
+	"hylang",	"hylen",	"hym",		"hypp",
+	"hys",		"ie",		"if",		"ig",
+	"index",	"it",		"itc",		"IX",
+	"kern",		"kernafter",	"kernbefore",	"kernpair",
+	"lc",		"lc_ctype",	"lds",		"length",
+	"letadj",	"lf",		"lg",		"lhang",
+	"linetabs",	"lnr",		"lnrf",		"lpfx",
+	"ls",		"lsm",		"lt",		"mc",
+	"mediasize",	"minss",	"mk",		"mso",
+	"na",		"ne",		"nh",		"nhychar",
+	"nm",		"nn",		"nop",		"nr",
+	"nrf",		"nroff",	"ns",		"nx",
+	"open",		"opena",	"os",		"output",
+	"padj",		"papersize",	"pc",		"pev",
+	"pi",		"PI",		"pl",		"pm",
+	"pn",		"pnr",		"po",		"ps",
+	"psbb",		"pshape",	"pso",		"ptr",
+	"pvs",		"rchar",	"rd",		"recursionlimit",
+	"return",	"rfschar",	"rhang",	"rj",
+	"rm",		"rn",		"rnn",		"rr",
+	"rs",		"rt",		"schar",	"sentchar",
+	"shc",		"shift",	"sizes",	"so",
+	"spacewidth",	"special",	"spreadwarn",	"ss",
+	"sty",		"substring",	"sv",		"sy",
+	"T&",		"ta",		"tc",		"TE",
+	"TH",		"ti",		"tkf",		"tl",
+	"tm",		"tm1",		"tmc",		"tr",
+	"track",	"transchar",	"trf",		"trimat",
+	"trin",		"trnt",		"troff",	"TS",
+	"uf",		"ul",		"unformat",	"unwatch",
+	"unwatchn",	"vpt",		"vs",		"warn",
+	"warnscale",	"watch",	"watchlength",	"watchn",
+	"wh",		"while",	"write",	"writec",
+	"writem",	"xflag",	".",		NULL,
+	"text",
+	"Dd",		"Dt",		"Os",		"Sh",
+	"Ss",		"Pp",		"D1",		"Dl",
+	"Bd",		"Ed",		"Bl",		"El",
+	"It",		"Ad",		"An",		"Ap",
+	"Ar",		"Cd",		"Cm",		"Dv",
+	"Er",		"Ev",		"Ex",		"Fa",
+	"Fd",		"Fl",		"Fn",		"Ft",
+	"Ic",		"In",		"Li",		"Nd",
+	"Nm",		"Op",		"Ot",		"Pa",
+	"Rv",		"St",		"Va",		"Vt",
+	"Xr",		"%A",		"%B",		"%D",
+	"%I",		"%J",		"%N",		"%O",
+	"%P",		"%R",		"%T",		"%V",
+	"Ac",		"Ao",		"Aq",		"At",
+	"Bc",		"Bf",		"Bo",		"Bq",
+	"Bsx",		"Bx",		"Db",		"Dc",
+	"Do",		"Dq",		"Ec",		"Ef",
+	"Em",		"Eo",		"Fx",		"Ms",
+	"No",		"Ns",		"Nx",		"Ox",
+	"Pc",		"Pf",		"Po",		"Pq",
+	"Qc",		"Ql",		"Qo",		"Qq",
+	"Re",		"Rs",		"Sc",		"So",
+	"Sq",		"Sm",		"Sx",		"Sy",
+	"Tn",		"Ux",		"Xc",		"Xo",
+	"Fo",		"Fc",		"Oo",		"Oc",
+	"Bk",		"Ek",		"Bt",		"Hf",
+	"Fr",		"Ud",		"Lb",		"Lp",
+	"Lk",		"Mt",		"Brq",		"Bro",
+	"Brc",		"%C",		"Es",		"En",
+	"Dx",		"%Q",		"br",		"sp",
+	"%U",		"Ta",		"ll",		NULL,
+	"TH",		"SH",		"SS",		"TP",
+	"LP",		"PP",		"P",		"IP",
+	"HP",		"SM",		"SB",		"BI",
+	"IB",		"BR",		"RB",		"R",
+	"B",		"I",		"IR",		"RI",
+	"br",		"sp",		"nf",		"fi",
+	"RE",		"RS",		"DT",		"UC",
+	"PD",		"AT",		"in",		"ft",
+	"OP",		"EX",		"EE",		"UR",
+	"UE",		"ll",		NULL
+};
+const	char *const *roff_name = __roff_name;
+
 static	struct roffmac	*hash[HASHWIDTH];
 
-static	struct roffmac	 roffs[ROFF_MAX] = {
+static	struct roffmac	 roffs[TOKEN_NONE] = {
 	{ "ab", roff_unsupp, NULL, NULL, 0, NULL },
 	{ "ad", roff_line_ignore, NULL, NULL, 0, NULL },
 	{ "af", roff_line_ignore, NULL, NULL, 0, NULL },
@@ -764,10 +622,10 @@ roffhash_init(void)
 }
 
 /*
- * Look up a roff token by its name.  Returns ROFF_MAX if no macro by
+ * Look up a roff token by its name.  Returns TOKEN_NONE if no macro by
  * the nil-terminated string name could be found.
  */
-static enum rofft
+static enum roff_tok
 roffhash_find(const char *p, size_t s)
 {
 	int		 buc;
@@ -781,17 +639,17 @@ roffhash_find(const char *p, size_t s)
 	 */
 
 	if (p[0] < ASCII_LO || p[0] > ASCII_HI)
-		return ROFF_MAX;
+		return TOKEN_NONE;
 
 	buc = ROFF_HASH(p);
 
 	if (NULL == (n = hash[buc]))
-		return ROFF_MAX;
+		return TOKEN_NONE;
 	for ( ; n; n = n->next)
 		if (0 == strncmp(n->name, p, s) && '\0' == n->name[(int)s])
-			return (enum rofft)(n - roffs);
+			return (enum roff_tok)(n - roffs);
 
-	return ROFF_MAX;
+	return TOKEN_NONE;
 }
 
 /* --- stack of request blocks -------------------------------------------- */
@@ -819,7 +677,7 @@ roffnode_pop(struct roff *r)
  * removed with roffnode_pop().
  */
 static void
-roffnode_push(struct roff *r, enum rofft tok, const char *name,
+roffnode_push(struct roff *r, enum roff_tok tok, const char *name,
 		int line, int col)
 {
 	struct roffnode	*p;
@@ -1521,7 +1379,7 @@ roff_parsetext(struct buf *buf, int pos,
 enum rofferr
 roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs)
 {
-	enum rofft	 t;
+	enum roff_tok	 t;
 	enum rofferr	 e;
 	int		 pos;	/* parse point */
 	int		 spos;	/* saved parse point for messages */
@@ -1560,11 +1418,10 @@ roff_parseln(struct roff *r, int ln, str
 
 	if (r->last != NULL && ! ctl) {
 		t = r->last->tok;
-		assert(roffs[t].text);
 		e = (*roffs[t].text)(r, t, buf, ln, pos, pos, offs);
-		assert(e == ROFF_IGN || e == ROFF_CONT);
-		if (e != ROFF_CONT)
+		if (e == ROFF_IGN)
 			return e;
+		assert(e == ROFF_CONT);
 	}
 	if (r->eqn != NULL)
 		return eqn_read(&r->eqn, ln, buf->buf, ppos, offs);
@@ -1590,7 +1447,6 @@ roff_parseln(struct roff *r, int ln, str
 
 	if (r->last) {
 		t = r->last->tok;
-		assert(roffs[t].sub);
 		return (*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs);
 	}
 
@@ -1601,7 +1457,7 @@ roff_parseln(struct roff *r, int ln, str
 
 	/* Tables ignore most macros. */
 
-	if (r->tbl != NULL && (t == ROFF_MAX || t == ROFF_TS)) {
+	if (r->tbl != NULL && (t == TOKEN_NONE || t == ROFF_TS)) {
 		mandoc_msg(MANDOCERR_TBLMACRO, r->parse,
 		    ln, pos, buf->buf + spos);
 		if (t == ROFF_TS)
@@ -1618,12 +1474,11 @@ roff_parseln(struct roff *r, int ln, str
 	 * Let the standard macro set parsers handle it.
 	 */
 
-	if (t == ROFF_MAX)
+	if (t == TOKEN_NONE)
 		return ROFF_CONT;
 
 	/* Execute a roff request or a user defined macro. */
 
-	assert(roffs[t].proc);
 	return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);
 }
 
@@ -1653,18 +1508,18 @@ roff_endparse(struct roff *r)
  * Parse a roff node's type from the input buffer.  This must be in the
  * form of ".foo xxx" in the usual way.
  */
-static enum rofft
+static enum roff_tok
 roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos)
 {
 	char		*cp;
 	const char	*mac;
 	size_t		 maclen;
-	enum rofft	 t;
+	enum roff_tok	 t;
 
 	cp = buf + *pos;
 
 	if ('\0' == *cp || '"' == *cp || '\t' == *cp || ' ' == *cp)
-		return ROFF_MAX;
+		return TOKEN_NONE;
 
 	mac = cp;
 	maclen = roff_getname(r, &cp, ln, ppos);
@@ -1672,7 +1527,7 @@ roff_parse(struct roff *r, char *buf, in
 	t = (r->current_string = roff_getstrn(r, mac, maclen))
 	    ? ROFF_USERDEF : roffhash_find(mac, maclen);
 
-	if (ROFF_MAX != t)
+	if (t != TOKEN_NONE)
 		*pos = cp - buf;
 
 	return t;
@@ -1857,7 +1712,7 @@ roff_block(ROFF_ARGS)
 static enum rofferr
 roff_block_sub(ROFF_ARGS)
 {
-	enum rofft	t;
+	enum roff_tok	t;
 	int		i, j;
 
 	/*
@@ -1886,7 +1741,7 @@ roff_block_sub(ROFF_ARGS)
 
 			pos = i;
 			if (roff_parse(r, buf->buf, &pos, ln, ppos) !=
-			    ROFF_MAX)
+			    TOKEN_NONE)
 				return ROFF_RERUN;
 			return ROFF_IGN;
 		}
@@ -1905,7 +1760,6 @@ roff_block_sub(ROFF_ARGS)
 		return ROFF_IGN;
 	}
 
-	assert(roffs[t].proc);
 	return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);
 }
 
@@ -1922,7 +1776,7 @@ roff_block_text(ROFF_ARGS)
 static enum rofferr
 roff_cond_sub(ROFF_ARGS)
 {
-	enum rofft	 t;
+	enum roff_tok	 t;
 	char		*ep;
 	int		 rr;
 
@@ -1935,11 +1789,8 @@ roff_cond_sub(ROFF_ARGS)
 	 * required or when the conditional evaluated to true.
 	 */
 
-	if ((t != ROFF_MAX) &&
-	    (rr || roffs[t].flags & ROFFMAC_STRUCT)) {
-		assert(roffs[t].proc);
+	if (t != TOKEN_NONE && (rr || roffs[t].flags & ROFFMAC_STRUCT))
 		return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs);
-	}
 
 	/*
 	 * If `\}' occurs on a macro line without a preceding macro,
Index: mandocdb.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mandocdb.c,v
retrieving revision 1.245
retrieving revision 1.246
diff -Lmandocdb.c -Lmandocdb.c -u -p -r1.245 -r1.246
--- mandocdb.c
+++ mandocdb.c
@@ -183,8 +183,7 @@ static	struct ohash	 names; /* table of 
 static	struct ohash	 strings; /* table of all strings */
 static	uint64_t	 name_mask;
 
-static	const struct mdoc_handler mdocs[MDOC_MAX] = {
-	{ NULL, 0, 0 },  /* Ap */
+static	const struct mdoc_handler __mdocs[MDOC_MAX - MDOC_Dd] = {
 	{ NULL, 0, NODE_NOPRT },  /* Dd */
 	{ NULL, 0, NODE_NOPRT },  /* Dt */
 	{ NULL, 0, NODE_NOPRT },  /* Os */
@@ -200,6 +199,7 @@ static	const struct mdoc_handler mdocs[M
 	{ NULL, 0, 0 },  /* It */
 	{ NULL, 0, 0 },  /* Ad */
 	{ NULL, TYPE_An, 0 },  /* An */
+	{ NULL, 0, 0 },  /* Ap */
 	{ NULL, TYPE_Ar, 0 },  /* Ar */
 	{ NULL, TYPE_Cd, 0 },  /* Cd */
 	{ NULL, TYPE_Cm, 0 },  /* Cm */
@@ -308,6 +308,7 @@ static	const struct mdoc_handler mdocs[M
 	{ NULL, 0, 0 },  /* Ta */
 	{ NULL, 0, 0 },  /* ll */
 };
+static	const struct mdoc_handler *const mdocs = __mdocs - MDOC_Dd;
 
 
 int
@@ -1545,9 +1546,8 @@ parse_mdoc(struct mpage *mpage, const st
 	const struct roff_node *n)
 {
 
-	assert(NULL != n);
-	for (n = n->child; NULL != n; n = n->next) {
-		if (n->flags & mdocs[n->tok].taboo)
+	for (n = n->child; n != NULL; n = n->next) {
+		if (n->tok == TOKEN_NONE || n->flags & mdocs[n->tok].taboo)
 			continue;
 		switch (n->type) {
 		case ROFFT_ELEM:
@@ -1555,15 +1555,14 @@ parse_mdoc(struct mpage *mpage, const st
 		case ROFFT_HEAD:
 		case ROFFT_BODY:
 		case ROFFT_TAIL:
-			if (NULL != mdocs[n->tok].fp)
-			       if (0 == (*mdocs[n->tok].fp)(mpage, meta, n))
-				       break;
+			if (mdocs[n->tok].fp != NULL &&
+			    (*mdocs[n->tok].fp)(mpage, meta, n) == 0)
+				break;
 			if (mdocs[n->tok].mask)
 				putmdockey(mpage, n->child,
 				    mdocs[n->tok].mask, mdocs[n->tok].taboo);
 			break;
 		default:
-			assert(n->type != ROFFT_ROOT);
 			continue;
 		}
 		if (NULL != n->child)
Index: man_term.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man_term.c,v
retrieving revision 1.191
retrieving revision 1.192
diff -Lman_term.c -Lman_term.c -u -p -r1.191 -r1.192
--- man_term.c
+++ man_term.c
@@ -95,8 +95,7 @@ static	void		  post_SS(DECL_ARGS);
 static	void		  post_TP(DECL_ARGS);
 static	void		  post_UR(DECL_ARGS);
 
-static	const struct termact termacts[MAN_MAX] = {
-	{ pre_sp, NULL, MAN_NOTEXT }, /* br */
+static	const struct termact __termacts[MAN_MAX - MAN_TH] = {
 	{ NULL, NULL, 0 }, /* TH */
 	{ pre_SH, post_SH, 0 }, /* SH */
 	{ pre_SS, post_SS, 0 }, /* SS */
@@ -117,6 +116,7 @@ static	const struct termact termacts[MAN
 	{ pre_I, NULL, 0 }, /* I */
 	{ pre_alternate, NULL, 0 }, /* IR */
 	{ pre_alternate, NULL, 0 }, /* RI */
+	{ pre_sp, NULL, MAN_NOTEXT }, /* br */
 	{ pre_sp, NULL, MAN_NOTEXT }, /* sp */
 	{ pre_literal, NULL, 0 }, /* nf */
 	{ pre_literal, NULL, 0 }, /* fi */
@@ -135,6 +135,7 @@ static	const struct termact termacts[MAN
 	{ NULL, NULL, 0 }, /* UE */
 	{ pre_ll, NULL, MAN_NOTEXT }, /* ll */
 };
+static	const struct termact *termacts = __termacts - MAN_TH;
 
 
 void
Index: libmdoc.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/libmdoc.h,v
retrieving revision 1.109
retrieving revision 1.110
diff -Llibmdoc.h -Llibmdoc.h -u -p -r1.109 -r1.110
--- libmdoc.h
+++ libmdoc.h
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013, 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,7 +17,7 @@
  */
 
 #define	MACRO_PROT_ARGS	struct roff_man *mdoc, \
-			int tok, \
+			enum roff_tok tok, \
 			int line, \
 			int ppos, \
 			int *pos, \
@@ -65,24 +65,25 @@ extern	const struct mdoc_macro *const md
 
 void		  mdoc_macro(MACRO_PROT_ARGS);
 void		  mdoc_elem_alloc(struct roff_man *, int, int,
-			int, struct mdoc_arg *);
+			enum roff_tok, struct mdoc_arg *);
 struct roff_node *mdoc_block_alloc(struct roff_man *, int, int,
-			int, struct mdoc_arg *);
-void		  mdoc_tail_alloc(struct roff_man *, int, int, int);
-struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int,
-			struct roff_node *);
+			enum roff_tok, struct mdoc_arg *);
+void		  mdoc_tail_alloc(struct roff_man *, int, int,
+			enum roff_tok);
+struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int,
+			enum roff_tok, struct roff_node *);
 void		  mdoc_node_relink(struct roff_man *, struct roff_node *);
 void		  mdoc_node_validate(struct roff_man *);
 void		  mdoc_state(struct roff_man *, struct roff_node *);
 void		  mdoc_state_reset(struct roff_man *);
-int		  mdoc_hash_find(const char *);
+enum roff_tok	  mdoc_hash_find(const char *);
 const char	 *mdoc_a2arch(const char *);
 const char	 *mdoc_a2att(const char *);
 const char	 *mdoc_a2lib(const char *);
 enum roff_sec	  mdoc_a2sec(const char *);
 const char	 *mdoc_a2st(const char *);
-void		  mdoc_argv(struct roff_man *, int, int,
+void		  mdoc_argv(struct roff_man *, int, enum roff_tok,
 			struct mdoc_arg **, int *, char *);
 enum margserr	  mdoc_args(struct roff_man *, int,
-			int *, char *, int, char **);
+			int *, char *, enum roff_tok, char **);
 enum mdelim	  mdoc_isdelim(const char *);
Index: mandoc_headers.3
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mandoc_headers.3,v
retrieving revision 1.9
retrieving revision 1.10
diff -Lmandoc_headers.3 -Lmandoc_headers.3 -u -p -r1.9 -r1.10
--- mandoc_headers.3
+++ mandoc_headers.3
@@ -118,10 +118,13 @@ Provides
 .Vt enum roff_macroset ,
 .Vt enum roff_next ,
 .Vt enum roff_sec ,
+.Vt enum roff_tok ,
 .Vt enum roff_type ,
 .Vt struct roff_man ,
 .Vt struct roff_meta ,
 .Vt struct roff_node ,
+the constant array
+.Va roff_name
 and the function
 .Fn deroff .
 .Pp
@@ -272,6 +275,10 @@ from
 as opaque types for function prototypes.
 .It Qq Pa libmdoc.h
 Requires
+.Qq Pa roff.h
+for
+.Vt enum roff_tok
+and
 .Qq Pa mdoc.h
 for
 .Vt enum mdoc_*
@@ -304,6 +311,10 @@ When this header is included, the same f
 or
 .Pa libroff.h .
 .It Qq Pa libman.h
+Requires
+.Qq Pa roff.h
+for
+.Vt enum roff_tok .
 Provides
 .Vt struct man_macro
 and some functions internal to the
Index: man.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man.c,v
retrieving revision 1.168
retrieving revision 1.169
diff -Lman.c -Lman.c -u -p -r1.168 -r1.169
--- man.c
+++ man.c
@@ -35,21 +35,6 @@
 #include "roff_int.h"
 #include "libman.h"
 
-const	char *const __man_macronames[MAN_MAX] = {
-	"br",		"TH",		"SH",		"SS",
-	"TP",		"LP",		"PP",		"P",
-	"IP",		"HP",		"SM",		"SB",
-	"BI",		"IB",		"BR",		"RB",
-	"R",		"B",		"I",		"IR",
-	"RI",		"sp",		"nf",
-	"fi",		"RE",		"RS",		"DT",
-	"UC",		"PD",		"AT",		"in",
-	"ft",		"OP",		"EX",		"EE",
-	"UR",		"UE",		"ll"
-	};
-
-const	char * const *man_macronames = __man_macronames;
-
 static	void		 man_descope(struct roff_man *, int, int);
 static	int		 man_ptext(struct roff_man *, int, char *, int);
 static	int		 man_pmacro(struct roff_man *, int, char *, int);
@@ -275,8 +260,8 @@ man_breakscope(struct roff_man *man, int
 
 		mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
 		    n->line, n->pos, "%s breaks %s",
-		    tok == TOKEN_NONE ? "TS" : man_macronames[tok],
-		    man_macronames[n->tok]);
+		    tok == TOKEN_NONE ? "TS" : roff_name[tok],
+		    roff_name[n->tok]);
 
 		roff_node_delete(man, n);
 		man->flags &= ~MAN_ELINE;
@@ -317,8 +302,8 @@ man_breakscope(struct roff_man *man, int
 
 		mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse,
 		    n->line, n->pos, "%s breaks %s",
-		    tok == TOKEN_NONE ? "TS" : man_macronames[tok],
-		    man_macronames[n->tok]);
+		    tok == TOKEN_NONE ? "TS" : roff_name[tok],
+		    roff_name[n->tok]);
 
 		roff_node_delete(man, n);
 		man->flags &= ~MAN_BLINE;
Index: tree.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/tree.c,v
retrieving revision 1.73
retrieving revision 1.74
diff -Ltree.c -Ltree.c -u -p -r1.73 -r1.74
--- tree.c
+++ tree.c
@@ -129,23 +129,23 @@ print_mdoc(const struct roff_node *n, in
 		p = n->string;
 		break;
 	case ROFFT_BODY:
-		p = mdoc_macronames[n->tok];
+		p = roff_name[n->tok];
 		break;
 	case ROFFT_HEAD:
-		p = mdoc_macronames[n->tok];
+		p = roff_name[n->tok];
 		break;
 	case ROFFT_TAIL:
-		p = mdoc_macronames[n->tok];
+		p = roff_name[n->tok];
 		break;
 	case ROFFT_ELEM:
-		p = mdoc_macronames[n->tok];
+		p = roff_name[n->tok];
 		if (n->args) {
 			argv = n->args->argv;
 			argc = n->args->argc;
 		}
 		break;
 	case ROFFT_BLOCK:
-		p = mdoc_macronames[n->tok];
+		p = roff_name[n->tok];
 		if (n->args) {
 			argv = n->args->argv;
 			argc = n->args->argc;
@@ -257,7 +257,7 @@ print_man(const struct roff_node *n, int
 	case ROFFT_BLOCK:
 	case ROFFT_HEAD:
 	case ROFFT_BODY:
-		p = man_macronames[n->tok];
+		p = roff_name[n->tok];
 		break;
 	case ROFFT_ROOT:
 		p = "root";
Index: mdoc.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.c,v
retrieving revision 1.261
retrieving revision 1.262
diff -Lmdoc.c -Lmdoc.c -u -p -r1.261 -r1.262
--- mdoc.c
+++ mdoc.c
@@ -35,41 +35,6 @@
 #include "roff_int.h"
 #include "libmdoc.h"
 
-const	char *const __mdoc_macronames[MDOC_MAX + 1] = {
-	"text",
-	"Ap",		"Dd",		"Dt",		"Os",
-	"Sh",		"Ss",		"Pp",		"D1",
-	"Dl",		"Bd",		"Ed",		"Bl",
-	"El",		"It",		"Ad",		"An",
-	"Ar",		"Cd",		"Cm",		"Dv",
-	"Er",		"Ev",		"Ex",		"Fa",
-	"Fd",		"Fl",		"Fn",		"Ft",
-	"Ic",		"In",		"Li",		"Nd",
-	"Nm",		"Op",		"Ot",		"Pa",
-	"Rv",		"St",		"Va",		"Vt",
-	"Xr",		"%A",		"%B",		"%D",
-	"%I",		"%J",		"%N",		"%O",
-	"%P",		"%R",		"%T",		"%V",
-	"Ac",		"Ao",		"Aq",		"At",
-	"Bc",		"Bf",		"Bo",		"Bq",
-	"Bsx",		"Bx",		"Db",		"Dc",
-	"Do",		"Dq",		"Ec",		"Ef",
-	"Em",		"Eo",		"Fx",		"Ms",
-	"No",		"Ns",		"Nx",		"Ox",
-	"Pc",		"Pf",		"Po",		"Pq",
-	"Qc",		"Ql",		"Qo",		"Qq",
-	"Re",		"Rs",		"Sc",		"So",
-	"Sq",		"Sm",		"Sx",		"Sy",
-	"Tn",		"Ux",		"Xc",		"Xo",
-	"Fo",		"Fc",		"Oo",		"Oc",
-	"Bk",		"Ek",		"Bt",		"Hf",
-	"Fr",		"Ud",		"Lb",		"Lp",
-	"Lk",		"Mt",		"Brq",		"Bro",
-	"Brc",		"%C",		"Es",		"En",
-	"Dx",		"%Q",		"br",		"sp",
-	"%U",		"Ta",		"ll",
-};
-
 const	char *const __mdoc_argnames[MDOC_ARG_MAX] = {
 	"split",		"nosplit",		"ragged",
 	"unfilled",		"literal",		"file",
@@ -80,9 +45,7 @@ const	char *const __mdoc_argnames[MDOC_A
 	"width",		"compact",		"std",
 	"filled",		"words",		"emphasis",
 	"symbolic",		"nested",		"centered"
-	};
-
-const	char * const *mdoc_macronames = __mdoc_macronames + 1;
+};
 const	char * const *mdoc_argnames = __mdoc_argnames;
 
 static	int		  mdoc_ptext(struct roff_man *, int, char *, int);
@@ -119,13 +82,12 @@ mdoc_parseln(struct roff_man *mdoc, int 
 void
 mdoc_macro(MACRO_PROT_ARGS)
 {
-	assert(tok > TOKEN_NONE && tok < MDOC_MAX);
-
+	assert(tok >= MDOC_Dd && tok < MDOC_MAX);
 	(*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf);
 }
 
 void
-mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok)
+mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, enum roff_tok tok)
 {
 	struct roff_node *p;
 
@@ -135,8 +97,8 @@ mdoc_tail_alloc(struct roff_man *mdoc, i
 }
 
 struct roff_node *
-mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok,
-		struct roff_node *body)
+mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos,
+    enum roff_tok tok, struct roff_node *body)
 {
 	struct roff_node *p;
 
@@ -153,7 +115,7 @@ mdoc_endbody_alloc(struct roff_man *mdoc
 
 struct roff_node *
 mdoc_block_alloc(struct roff_man *mdoc, int line, int pos,
-	int tok, struct mdoc_arg *args)
+    enum roff_tok tok, struct mdoc_arg *args)
 {
 	struct roff_node *p;
 
@@ -180,7 +142,7 @@ mdoc_block_alloc(struct roff_man *mdoc, 
 
 void
 mdoc_elem_alloc(struct roff_man *mdoc, int line, int pos,
-	int tok, struct mdoc_arg *args)
+     enum roff_tok tok, struct mdoc_arg *args)
 {
 	struct roff_node *p;
 
@@ -340,7 +302,7 @@ mdoc_pmacro(struct roff_man *mdoc, int l
 {
 	struct roff_node *n;
 	const char	 *cp;
-	int		  tok;
+	enum roff_tok	  tok;
 	int		  i, sv;
 	char		  mac[5];
 
Index: roff.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/roff.h,v
retrieving revision 1.40
retrieving revision 1.41
diff -Lroff.h -Lroff.h -u -p -r1.40 -r1.41
--- roff.h
+++ roff.h
@@ -64,6 +64,416 @@ enum	roff_type {
 	ROFFT_EQN
 };
 
+enum	roff_tok {
+	ROFF_ab = 0,
+	ROFF_ad,
+	ROFF_af,
+	ROFF_aln,
+	ROFF_als,
+	ROFF_am,
+	ROFF_am1,
+	ROFF_ami,
+	ROFF_ami1,
+	ROFF_as,
+	ROFF_as1,
+	ROFF_asciify,
+	ROFF_backtrace,
+	ROFF_bd,
+	ROFF_bleedat,
+	ROFF_blm,
+	ROFF_box,
+	ROFF_boxa,
+	ROFF_bp,
+	ROFF_BP,
+	/* MAN_br, MDOC_br */
+	ROFF_break,
+	ROFF_breakchar,
+	ROFF_brnl,
+	ROFF_brp,
+	ROFF_brpnl,
+	ROFF_c2,
+	ROFF_cc,
+	ROFF_ce,
+	ROFF_cf,
+	ROFF_cflags,
+	ROFF_ch,
+	ROFF_char,
+	ROFF_chop,
+	ROFF_class,
+	ROFF_close,
+	ROFF_CL,
+	ROFF_color,
+	ROFF_composite,
+	ROFF_continue,
+	ROFF_cp,
+	ROFF_cropat,
+	ROFF_cs,
+	ROFF_cu,
+	ROFF_da,
+	ROFF_dch,
+	ROFF_Dd,
+	ROFF_de,
+	ROFF_de1,
+	ROFF_defcolor,
+	ROFF_dei,
+	ROFF_dei1,
+	ROFF_device,
+	ROFF_devicem,
+	ROFF_di,
+	ROFF_do,
+	ROFF_ds,
+	ROFF_ds1,
+	ROFF_dwh,
+	ROFF_dt,
+	ROFF_ec,
+	ROFF_ecr,
+	ROFF_ecs,
+	ROFF_el,
+	ROFF_em,
+	ROFF_EN,
+	ROFF_eo,
+	ROFF_EP,
+	ROFF_EQ,
+	ROFF_errprint,
+	ROFF_ev,
+	ROFF_evc,
+	ROFF_ex,
+	ROFF_fallback,
+	ROFF_fam,
+	ROFF_fc,
+	ROFF_fchar,
+	ROFF_fcolor,
+	ROFF_fdeferlig,
+	ROFF_feature,
+	/* MAN_fi; ignored in mdoc(7) */
+	ROFF_fkern,
+	ROFF_fl,
+	ROFF_flig,
+	ROFF_fp,
+	ROFF_fps,
+	ROFF_fschar,
+	ROFF_fspacewidth,
+	ROFF_fspecial,
+	/* MAN_ft; ignored in mdoc(7) */
+	ROFF_ftr,
+	ROFF_fzoom,
+	ROFF_gcolor,
+	ROFF_hc,
+	ROFF_hcode,
+	ROFF_hidechar,
+	ROFF_hla,
+	ROFF_hlm,
+	ROFF_hpf,
+	ROFF_hpfa,
+	ROFF_hpfcode,
+	ROFF_hw,
+	ROFF_hy,
+	ROFF_hylang,
+	ROFF_hylen,
+	ROFF_hym,
+	ROFF_hypp,
+	ROFF_hys,
+	ROFF_ie,
+	ROFF_if,
+	ROFF_ig,
+	/* MAN_in; ignored in mdoc(7) */
+	ROFF_index,
+	ROFF_it,
+	ROFF_itc,
+	ROFF_IX,
+	ROFF_kern,
+	ROFF_kernafter,
+	ROFF_kernbefore,
+	ROFF_kernpair,
+	ROFF_lc,
+	ROFF_lc_ctype,
+	ROFF_lds,
+	ROFF_length,
+	ROFF_letadj,
+	ROFF_lf,
+	ROFF_lg,
+	ROFF_lhang,
+	ROFF_linetabs,
+	/* MAN_ll, MDOC_ll */
+	ROFF_lnr,
+	ROFF_lnrf,
+	ROFF_lpfx,
+	ROFF_ls,
+	ROFF_lsm,
+	ROFF_lt,
+	ROFF_mc,
+	ROFF_mediasize,
+	ROFF_minss,
+	ROFF_mk,
+	ROFF_mso,
+	ROFF_na,
+	ROFF_ne,
+	/* MAN_nf; ignored in mdoc(7) */
+	ROFF_nh,
+	ROFF_nhychar,
+	ROFF_nm,
+	ROFF_nn,
+	ROFF_nop,
+	ROFF_nr,
+	ROFF_nrf,
+	ROFF_nroff,
+	ROFF_ns,
+	ROFF_nx,
+	ROFF_open,
+	ROFF_opena,
+	ROFF_os,
+	ROFF_output,
+	ROFF_padj,
+	ROFF_papersize,
+	ROFF_pc,
+	ROFF_pev,
+	ROFF_pi,
+	ROFF_PI,
+	ROFF_pl,
+	ROFF_pm,
+	ROFF_pn,
+	ROFF_pnr,
+	ROFF_po,
+	ROFF_ps,
+	ROFF_psbb,
+	ROFF_pshape,
+	ROFF_pso,
+	ROFF_ptr,
+	ROFF_pvs,
+	ROFF_rchar,
+	ROFF_rd,
+	ROFF_recursionlimit,
+	ROFF_return,
+	ROFF_rfschar,
+	ROFF_rhang,
+	ROFF_rj,
+	ROFF_rm,
+	ROFF_rn,
+	ROFF_rnn,
+	ROFF_rr,
+	ROFF_rs,
+	ROFF_rt,
+	ROFF_schar,
+	ROFF_sentchar,
+	ROFF_shc,
+	ROFF_shift,
+	ROFF_sizes,
+	ROFF_so,
+	/* MAN_sp, MDOC_sp */
+	ROFF_spacewidth,
+	ROFF_special,
+	ROFF_spreadwarn,
+	ROFF_ss,
+	ROFF_sty,
+	ROFF_substring,
+	ROFF_sv,
+	ROFF_sy,
+	ROFF_T_,
+	ROFF_ta,
+	ROFF_tc,
+	ROFF_TE,
+	ROFF_TH,
+	ROFF_ti,
+	ROFF_tkf,
+	ROFF_tl,
+	ROFF_tm,
+	ROFF_tm1,
+	ROFF_tmc,
+	ROFF_tr,
+	ROFF_track,
+	ROFF_transchar,
+	ROFF_trf,
+	ROFF_trimat,
+	ROFF_trin,
+	ROFF_trnt,
+	ROFF_troff,
+	ROFF_TS,
+	ROFF_uf,
+	ROFF_ul,
+	ROFF_unformat,
+	ROFF_unwatch,
+	ROFF_unwatchn,
+	ROFF_vpt,
+	ROFF_vs,
+	ROFF_warn,
+	ROFF_warnscale,
+	ROFF_watch,
+	ROFF_watchlength,
+	ROFF_watchn,
+	ROFF_wh,
+	ROFF_while,
+	ROFF_write,
+	ROFF_writec,
+	ROFF_writem,
+	ROFF_xflag,
+	ROFF_cblock,
+	ROFF_USERDEF,
+	TOKEN_NONE,
+	MDOC_Dd,
+	MDOC_Dt,
+	MDOC_Os,
+	MDOC_Sh,
+	MDOC_Ss,
+	MDOC_Pp,
+	MDOC_D1,
+	MDOC_Dl,
+	MDOC_Bd,
+	MDOC_Ed,
+	MDOC_Bl,
+	MDOC_El,
+	MDOC_It,
+	MDOC_Ad,
+	MDOC_An,
+	MDOC_Ap,
+	MDOC_Ar,
+	MDOC_Cd,
+	MDOC_Cm,
+	MDOC_Dv,
+	MDOC_Er,
+	MDOC_Ev,
+	MDOC_Ex,
+	MDOC_Fa,
+	MDOC_Fd,
+	MDOC_Fl,
+	MDOC_Fn,
+	MDOC_Ft,
+	MDOC_Ic,
+	MDOC_In,
+	MDOC_Li,
+	MDOC_Nd,
+	MDOC_Nm,
+	MDOC_Op,
+	MDOC_Ot,
+	MDOC_Pa,
+	MDOC_Rv,
+	MDOC_St,
+	MDOC_Va,
+	MDOC_Vt,
+	MDOC_Xr,
+	MDOC__A,
+	MDOC__B,
+	MDOC__D,
+	MDOC__I,
+	MDOC__J,
+	MDOC__N,
+	MDOC__O,
+	MDOC__P,
+	MDOC__R,
+	MDOC__T,
+	MDOC__V,
+	MDOC_Ac,
+	MDOC_Ao,
+	MDOC_Aq,
+	MDOC_At,
+	MDOC_Bc,
+	MDOC_Bf,
+	MDOC_Bo,
+	MDOC_Bq,
+	MDOC_Bsx,
+	MDOC_Bx,
+	MDOC_Db,
+	MDOC_Dc,
+	MDOC_Do,
+	MDOC_Dq,
+	MDOC_Ec,
+	MDOC_Ef,
+	MDOC_Em,
+	MDOC_Eo,
+	MDOC_Fx,
+	MDOC_Ms,
+	MDOC_No,
+	MDOC_Ns,
+	MDOC_Nx,
+	MDOC_Ox,
+	MDOC_Pc,
+	MDOC_Pf,
+	MDOC_Po,
+	MDOC_Pq,
+	MDOC_Qc,
+	MDOC_Ql,
+	MDOC_Qo,
+	MDOC_Qq,
+	MDOC_Re,
+	MDOC_Rs,
+	MDOC_Sc,
+	MDOC_So,
+	MDOC_Sq,
+	MDOC_Sm,
+	MDOC_Sx,
+	MDOC_Sy,
+	MDOC_Tn,
+	MDOC_Ux,
+	MDOC_Xc,
+	MDOC_Xo,
+	MDOC_Fo,
+	MDOC_Fc,
+	MDOC_Oo,
+	MDOC_Oc,
+	MDOC_Bk,
+	MDOC_Ek,
+	MDOC_Bt,
+	MDOC_Hf,
+	MDOC_Fr,
+	MDOC_Ud,
+	MDOC_Lb,
+	MDOC_Lp,
+	MDOC_Lk,
+	MDOC_Mt,
+	MDOC_Brq,
+	MDOC_Bro,
+	MDOC_Brc,
+	MDOC__C,
+	MDOC_Es,
+	MDOC_En,
+	MDOC_Dx,
+	MDOC__Q,
+	MDOC_br,
+	MDOC_sp,
+	MDOC__U,
+	MDOC_Ta,
+	MDOC_ll,
+	MDOC_MAX,
+	MAN_TH,
+	MAN_SH,
+	MAN_SS,
+	MAN_TP,
+	MAN_LP,
+	MAN_PP,
+	MAN_P,
+	MAN_IP,
+	MAN_HP,
+	MAN_SM,
+	MAN_SB,
+	MAN_BI,
+	MAN_IB,
+	MAN_BR,
+	MAN_RB,
+	MAN_R,
+	MAN_B,
+	MAN_I,
+	MAN_IR,
+	MAN_RI,
+	MAN_br,
+	MAN_sp,
+	MAN_nf,
+	MAN_fi,
+	MAN_RE,
+	MAN_RS,
+	MAN_DT,
+	MAN_UC,
+	MAN_PD,
+	MAN_AT,
+	MAN_in,
+	MAN_ft,
+	MAN_OP,
+	MAN_EX,
+	MAN_EE,
+	MAN_UR,
+	MAN_UE,
+	MAN_ll,
+	MAN_MAX
+};
+
 enum	roff_next {
 	ROFF_NEXT_SIBLING = 0,
 	ROFF_NEXT_CHILD
@@ -94,8 +504,6 @@ struct	roff_node {
 	const struct eqn *eqn;	   /* EQN */
 	int		  line;    /* Input file line number. */
 	int		  pos;     /* Input file column number. */
-	int		  tok;     /* Request or macro ID. */
-#define	TOKEN_NONE	 (-1)	   /* No request or macro. */
 	int		  flags;
 #define	NODE_VALID	 (1 << 0)  /* Has been validated. */
 #define	NODE_ENDED	 (1 << 1)  /* Gone past body end mark. */
@@ -109,6 +517,7 @@ struct	roff_node {
 #define	NODE_NOPRT	 (1 << 9)  /* Shall not print anything. */
 	int		  prev_font; /* Before entering this node. */
 	int		  aux;     /* Decoded node data, type-dependent. */
+	enum roff_tok	  tok;     /* Request or macro ID. */
 	enum roff_type	  type;    /* AST node type. */
 	enum roff_sec	  sec;     /* Current named section. */
 	enum mdoc_endbody end;     /* BODY */
@@ -158,5 +567,6 @@ struct	roff_man {
 	enum roff_next	  next;    /* Where to put the next node. */
 };
 
+extern	const char *const *roff_name;
 
 void		 deroff(char **, const struct roff_node *);
Index: mdoc_markdown.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_markdown.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -Lmdoc_markdown.c -Lmdoc_markdown.c -u -p -r1.16 -r1.17
--- mdoc_markdown.c
+++ mdoc_markdown.c
@@ -103,8 +103,7 @@ static	void	 md_post_Pf(struct roff_node
 static	void	 md_post_Vt(struct roff_node *);
 static	void	 md_post__T(struct roff_node *);
 
-static	const struct md_act md_acts[MDOC_MAX + 1] = {
-	{ NULL, md_pre_Ap, NULL, NULL, NULL }, /* Ap */
+static	const struct md_act __md_acts[MDOC_MAX - MDOC_Dd] = {
 	{ NULL, NULL, NULL, NULL, NULL }, /* Dd */
 	{ NULL, NULL, NULL, NULL, NULL }, /* Dt */
 	{ NULL, NULL, NULL, NULL, NULL }, /* Os */
@@ -120,6 +119,7 @@ static	const struct md_act md_acts[MDOC_
 	{ NULL, md_pre_It, md_post_It, NULL, NULL }, /* It */
 	{ NULL, md_pre_raw, md_post_raw, "*", "*" }, /* Ad */
 	{ NULL, md_pre_An, NULL, NULL, NULL }, /* An */
+	{ NULL, md_pre_Ap, NULL, NULL, NULL }, /* Ap */
 	{ NULL, md_pre_raw, md_post_raw, "*", "*" }, /* Ar */
 	{ NULL, md_pre_raw, md_post_raw, "**", "**" }, /* Cd */
 	{ NULL, md_pre_raw, md_post_raw, "**", "**" }, /* Cm */
@@ -227,8 +227,8 @@ static	const struct md_act md_acts[MDOC_
 	{ NULL, md_pre_Lk, md_post_pc, NULL, NULL }, /* %U */
 	{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
 	{ NULL, NULL, NULL, NULL, NULL }, /* ll */
-	{ NULL, NULL, NULL, NULL, NULL }, /* ROOT */
 };
+static	const struct md_act *const md_acts = __md_acts - MDOC_Dd;
 
 static	int	 outflags;
 #define	MD_spc		 (1 << 0)  /* Blank character before next word. */
Index: mdoc_man.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_man.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -Lmdoc_man.c -Lmdoc_man.c -u -p -r1.108 -r1.109
--- mdoc_man.c
+++ mdoc_man.c
@@ -119,8 +119,7 @@ static	void	  print_width(const struct m
 static	void	  print_count(int *);
 static	void	  print_node(DECL_ARGS);
 
-static	const struct manact manacts[MDOC_MAX + 1] = {
-	{ NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
+static	const struct manact __manacts[MDOC_MAX - MDOC_Dd] = {
 	{ NULL, NULL, NULL, NULL, NULL }, /* Dd */
 	{ NULL, NULL, NULL, NULL, NULL }, /* Dt */
 	{ NULL, NULL, NULL, NULL, NULL }, /* Os */
@@ -136,6 +135,7 @@ static	const struct manact manacts[MDOC_
 	{ NULL, pre_it, post_it, NULL, NULL }, /* It */
 	{ NULL, pre_em, post_font, NULL, NULL }, /* Ad */
 	{ NULL, pre_an, NULL, NULL, NULL }, /* An */
+	{ NULL, pre_ap, NULL, NULL, NULL }, /* Ap */
 	{ NULL, pre_em, post_font, NULL, NULL }, /* Ar */
 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Cd */
 	{ NULL, pre_sy, post_font, NULL, NULL }, /* Cm */
@@ -243,8 +243,8 @@ static	const struct manact manacts[MDOC_
 	{ NULL, NULL, post_percent, NULL, NULL }, /* %U */
 	{ NULL, NULL, NULL, NULL, NULL }, /* Ta */
 	{ NULL, pre_ll, post_sp, NULL, NULL }, /* ll */
-	{ NULL, NULL, NULL, NULL, NULL }, /* ROOT */
 };
+static	const struct manact *const manacts = __manacts - MDOC_Dd;
 
 static	int		outflags;
 #define	MMAN_spc	(1 << 0)  /* blank character before next word */
Index: man_hash.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man_hash.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -Lman_hash.c -Lman_hash.c -u -p -r1.35 -r1.36
--- man_hash.c
+++ man_hash.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -60,8 +60,8 @@ man_hash_init(void)
 
 	memset(table, UCHAR_MAX, sizeof(table));
 
-	for (i = 0; i < (int)MAN_MAX; i++) {
-		x = man_macronames[i][0];
+	for (i = 0; i < (int)(MAN_MAX - MAN_TH); i++) {
+		x = *roff_name[MAN_TH + i];
 
 		assert(isalpha((unsigned char)x));
 
@@ -77,11 +77,10 @@ man_hash_init(void)
 	}
 }
 
-int
+enum roff_tok
 man_hash_find(const char *tmp)
 {
 	int		 x, y, i;
-	int		 tok;
 
 	if ('\0' == (x = tmp[0]))
 		return TOKEN_NONE;
@@ -94,9 +93,8 @@ man_hash_find(const char *tmp)
 		if (UCHAR_MAX == (y = table[x + i]))
 			return TOKEN_NONE;
 
-		tok = y;
-		if (0 == strcmp(tmp, man_macronames[tok]))
-			return tok;
+		if (strcmp(tmp, roff_name[MAN_TH + y]) == 0)
+			return MAN_TH + y;
 	}
 
 	return TOKEN_NONE;
Index: mdoc_hash.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_hash.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -Lmdoc_hash.c -Lmdoc_hash.c -u -p -r1.27 -r1.28
--- mdoc_hash.c
+++ mdoc_hash.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -46,8 +46,8 @@ mdoc_hash_init(void)
 
 	memset(table, UCHAR_MAX, sizeof(table));
 
-	for (i = 0; i < (int)MDOC_MAX; i++) {
-		p = mdoc_macronames[i];
+	for (i = 0; i < (int)(MDOC_MAX - MDOC_Dd); i++) {
+		p = roff_name[MDOC_Dd + i];
 
 		if (isalpha((unsigned char)p[1]))
 			major = 12 * (tolower((unsigned char)p[1]) - 97);
@@ -64,7 +64,7 @@ mdoc_hash_init(void)
 	}
 }
 
-int
+enum roff_tok
 mdoc_hash_find(const char *p)
 {
 	int		  major, i, j;
@@ -87,8 +87,8 @@ mdoc_hash_find(const char *p)
 	for (j = 0; j < 12; j++) {
 		if (UCHAR_MAX == (i = table[major + j]))
 			break;
-		if (0 == strcmp(p, mdoc_macronames[i]))
-			return i;
+		if (strcmp(p, roff_name[MDOC_Dd + i]) == 0)
+			return MDOC_Dd + i;
 	}
 
 	return TOKEN_NONE;
Index: mdoc_macro.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_macro.c,v
retrieving revision 1.218
retrieving revision 1.219
diff -Lmdoc_macro.c -Lmdoc_macro.c -u -p -r1.218 -r1.219
--- mdoc_macro.c
+++ mdoc_macro.c
@@ -46,21 +46,21 @@ static	void		phrase_ta(MACRO_PROT_ARGS);
 static	void		append_delims(struct roff_man *, int, int *, char *);
 static	void		dword(struct roff_man *, int, int, const char *,
 				enum mdelim, int);
-static	int		find_pending(struct roff_man *, int, int, int,
-				struct roff_node *);
+static	int		find_pending(struct roff_man *, enum roff_tok,
+				int, int, struct roff_node *);
 static	int		lookup(struct roff_man *, int, int, int, const char *);
 static	int		macro_or_word(MACRO_PROT_ARGS, int);
 static	void		break_intermediate(struct roff_node *,
-			    struct roff_node *);
-static	int		parse_rest(struct roff_man *, int, int, int *, char *);
-static	int		rew_alt(int);
-static	void		rew_elem(struct roff_man *, int);
+				struct roff_node *);
+static	int		parse_rest(struct roff_man *, enum roff_tok,
+				int, int *, char *);
+static	enum roff_tok	rew_alt(enum roff_tok);
+static	void		rew_elem(struct roff_man *, enum roff_tok);
 static	void		rew_last(struct roff_man *, const struct roff_node *);
 static	void		rew_pending(struct roff_man *,
 				const struct roff_node *);
 
-const	struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
-	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
+const	struct mdoc_macro __mdoc_macros[MDOC_MAX - MDOC_Dd] = {
 	{ in_line_eoln, MDOC_PROLOGUE }, /* Dd */
 	{ in_line_eoln, MDOC_PROLOGUE }, /* Dt */
 	{ in_line_eoln, MDOC_PROLOGUE }, /* Os */
@@ -76,6 +76,7 @@ const	struct mdoc_macro __mdoc_macros[MD
 	{ blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
+	{ in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Cd */
 	{ in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
@@ -202,8 +203,7 @@ const	struct mdoc_macro __mdoc_macros[MD
 	{ phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
 	{ in_line_eoln, MDOC_PROLOGUE }, /* ll */
 };
-
-const	struct mdoc_macro * const mdoc_macros = __mdoc_macros;
+const	struct mdoc_macro *const mdoc_macros = __mdoc_macros - MDOC_Dd;
 
 
 /*
@@ -225,7 +225,7 @@ mdoc_endparse(struct roff_man *mdoc)
 		if (n->type == ROFFT_BLOCK &&
 		    mdoc_macros[n->tok].flags & MDOC_EXPLICIT)
 			mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse,
-			    n->line, n->pos, mdoc_macronames[n->tok]);
+			    n->line, n->pos, roff_name[n->tok]);
 
 	/* Rewind to the first. */
 
@@ -240,7 +240,7 @@ mdoc_endparse(struct roff_man *mdoc)
 static int
 lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p)
 {
-	int	 res;
+	enum roff_tok	 res;
 
 	if (mdoc->flags & MDOC_PHRASEQF) {
 		mdoc->flags &= ~MDOC_PHRASEQF;
@@ -324,8 +324,8 @@ rew_pending(struct roff_man *mdoc, const
  * For a block closing macro, return the corresponding opening one.
  * Otherwise, return the macro itself.
  */
-static int
-rew_alt(int tok)
+static enum roff_tok
+rew_alt(enum roff_tok tok)
 {
 	switch (tok) {
 	case MDOC_Ac:
@@ -366,7 +366,7 @@ rew_alt(int tok)
 }
 
 static void
-rew_elem(struct roff_man *mdoc, int tok)
+rew_elem(struct roff_man *mdoc, enum roff_tok tok)
 {
 	struct roff_node *n;
 
@@ -398,7 +398,7 @@ break_intermediate(struct roff_node *n, 
  * the rew_pending() call closing out the sub-block.
  */
 static int
-find_pending(struct roff_man *mdoc, int tok, int line, int ppos,
+find_pending(struct roff_man *mdoc, enum roff_tok tok, int line, int ppos,
 	struct roff_node *target)
 {
 	struct roff_node	*n;
@@ -420,8 +420,8 @@ find_pending(struct roff_man *mdoc, int 
 			else if ( ! (target->flags & NODE_ENDED)) {
 				mandoc_vmsg(MANDOCERR_BLK_NEST,
 				    mdoc->parse, line, ppos,
-				    "%s breaks %s", mdoc_macronames[tok],
-				    mdoc_macronames[n->tok]);
+				    "%s breaks %s", roff_name[tok],
+				    roff_name[n->tok]);
 				mdoc_endbody_alloc(mdoc, line, ppos,
 				    tok, target);
 			}
@@ -524,7 +524,8 @@ macro_or_word(MACRO_PROT_ARGS, int parse
 		    mdoc_macros[tok].flags & MDOC_JOIN);
 		return 0;
 	} else {
-		if (mdoc_macros[tok].fp == in_line_eoln)
+		if (tok != TOKEN_NONE &&
+		    mdoc_macros[tok].fp == in_line_eoln)
 			rew_elem(mdoc, tok);
 		mdoc_macro(mdoc, ntok, line, ppos, pos, buf);
 		if (tok == TOKEN_NONE)
@@ -548,7 +549,7 @@ blk_exp_close(MACRO_PROT_ARGS)
 
 	int		 j, lastarg, maxargs, nl, pending;
 	enum margserr	 ac;
-	int		 atok, ntok;
+	enum roff_tok	 atok, ntok;
 	char		*p;
 
 	nl = MDOC_NEWLINE & mdoc->flags;
@@ -633,8 +634,7 @@ blk_exp_close(MACRO_PROT_ARGS)
 
 			mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse,
 			    line, ppos, "%s breaks %s",
-			    mdoc_macronames[atok],
-			    mdoc_macronames[later->tok]);
+			    roff_name[atok], roff_name[later->tok]);
 
 			endbody = mdoc_endbody_alloc(mdoc, line, ppos,
 			    atok, body);
@@ -676,7 +676,7 @@ blk_exp_close(MACRO_PROT_ARGS)
 
 	if (body == NULL) {
 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,
-		    line, ppos, mdoc_macronames[tok]);
+		    line, ppos, roff_name[tok]);
 		if (maxargs && endbody == NULL) {
 			/*
 			 * Stray .Ec without previous .Eo:
@@ -695,7 +695,7 @@ blk_exp_close(MACRO_PROT_ARGS)
 		if (buf[*pos] != '\0')
 			mandoc_vmsg(MANDOCERR_ARG_SKIP,
 			    mdoc->parse, line, ppos,
-			    "%s %s", mdoc_macronames[tok],
+			    "%s %s", roff_name[tok],
 			    buf + *pos);
 		if (endbody == NULL && n != NULL)
 			rew_pending(mdoc, n);
@@ -752,7 +752,7 @@ static void
 in_line(MACRO_PROT_ARGS)
 {
 	int		 la, scope, cnt, firstarg, mayopen, nc, nl;
-	int		 ntok;
+	enum roff_tok	 ntok;
 	enum margserr	 ac;
 	enum mdelim	 d;
 	struct mdoc_arg	*arg;
@@ -833,7 +833,7 @@ in_line(MACRO_PROT_ARGS)
 				mdoc_argv_free(arg);
 				mandoc_msg(MANDOCERR_MACRO_EMPTY,
 				    mdoc->parse, line, ppos,
-				    mdoc_macronames[tok]);
+				    roff_name[tok]);
 			}
 			mdoc_macro(mdoc, ntok, line, la, pos, buf);
 			if (nl)
@@ -881,7 +881,7 @@ in_line(MACRO_PROT_ARGS)
 		}
 
 		dword(mdoc, line, la, p, d,
-		    MDOC_JOIN & mdoc_macros[tok].flags);
+		    mdoc_macros[tok].flags & MDOC_JOIN);
 
 		/*
 		 * If the first argument is a closing delimiter,
@@ -921,7 +921,7 @@ in_line(MACRO_PROT_ARGS)
 		} else {
 			mdoc_argv_free(arg);
 			mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
-			    line, ppos, mdoc_macronames[tok]);
+			    line, ppos, roff_name[tok]);
 		}
 	}
 	if (nl)
@@ -946,7 +946,7 @@ blk_full(MACRO_PROT_ARGS)
 
 	if (buf[*pos] == '\0' && (tok == MDOC_Sh || tok == MDOC_Ss)) {
 		mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
-		    line, ppos, mdoc_macronames[tok]);
+		    line, ppos, roff_name[tok]);
 		return;
 	}
 
@@ -969,7 +969,7 @@ blk_full(MACRO_PROT_ARGS)
 					mandoc_vmsg(MANDOCERR_BLK_BROKEN,
 					    mdoc->parse, line, ppos,
 					    "It breaks %s",
-					    mdoc_macronames[blk->tok]);
+					    roff_name[blk->tok]);
 					rew_pending(mdoc, blk);
 				}
 				break;
@@ -981,9 +981,8 @@ blk_full(MACRO_PROT_ARGS)
 				case MDOC_Ss:
 					mandoc_vmsg(MANDOCERR_BLK_BROKEN,
 					    mdoc->parse, line, ppos,
-					    "%s breaks %s",
-					    mdoc_macronames[tok],
-					    mdoc_macronames[n->tok]);
+					    "%s breaks %s", roff_name[tok],
+					    roff_name[n->tok]);
 					rew_pending(mdoc, n);
 					n = mdoc->last;
 					continue;
@@ -1009,8 +1008,7 @@ blk_full(MACRO_PROT_ARGS)
 			if (blk != NULL) {
 				mandoc_vmsg(MANDOCERR_BLK_BROKEN,
 				    mdoc->parse, line, ppos,
-				    "It breaks %s",
-				    mdoc_macronames[blk->tok]);
+				    "It breaks %s", roff_name[blk->tok]);
 				rew_pending(mdoc, blk);
 				blk = NULL;
 			}
@@ -1103,7 +1101,7 @@ blk_full(MACRO_PROT_ARGS)
 		if (tok == MDOC_Bd || tok == MDOC_Bk) {
 			mandoc_vmsg(MANDOCERR_ARG_EXCESS,
 			    mdoc->parse, line, la, "%s ... %s",
-			    mdoc_macronames[tok], buf + la);
+			    roff_name[tok], buf + la);
 			break;
 		}
 		if (tok == MDOC_Rs) {
@@ -1311,7 +1309,7 @@ in_line_argn(MACRO_PROT_ARGS)
 	struct mdoc_arg	*arg;
 	char		*p;
 	enum margserr	 ac;
-	int		 ntok;
+	enum roff_tok	 ntok;
 	int		 state; /* arg#; -1: not yet open; -2: closed */
 	int		 la, maxargs, nl;
 
@@ -1401,12 +1399,12 @@ in_line_argn(MACRO_PROT_ARGS)
 		}
 
 		dword(mdoc, line, la, p, DELIM_MAX,
-		    MDOC_JOIN & mdoc_macros[tok].flags);
+		    mdoc_macros[tok].flags & MDOC_JOIN);
 	}
 
 	if (state == -1) {
 		mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
-		    line, ppos, mdoc_macronames[tok]);
+		    line, ppos, roff_name[tok]);
 		return;
 	}
 
@@ -1434,9 +1432,9 @@ in_line_eoln(MACRO_PROT_ARGS)
 	}
 
 	if (buf[*pos] == '\0' &&
-	    (tok == MDOC_Fd || mdoc_macronames[tok][0] == '%')) {
+	    (tok == MDOC_Fd || *roff_name[tok] == '%')) {
 		mandoc_msg(MANDOCERR_MACRO_EMPTY, mdoc->parse,
-		    line, ppos, mdoc_macronames[tok]);
+		    line, ppos, roff_name[tok]);
 		return;
 	}
 
@@ -1453,7 +1451,8 @@ in_line_eoln(MACRO_PROT_ARGS)
  * or until the next macro, call that macro, and return 1.
  */
 static int
-parse_rest(struct roff_man *mdoc, int tok, int line, int *pos, char *buf)
+parse_rest(struct roff_man *mdoc, enum roff_tok tok,
+    int line, int *pos, char *buf)
 {
 	int		 la;
 
Index: mdoc.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc.h,v
retrieving revision 1.144
retrieving revision 1.145
diff -Lmdoc.h -Lmdoc.h -u -p -r1.144 -r1.145
--- mdoc.h
+++ mdoc.h
@@ -16,131 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define	MDOC_Ap    0
-#define	MDOC_Dd    1
-#define	MDOC_Dt    2
-#define	MDOC_Os    3
-#define	MDOC_Sh    4
-#define	MDOC_Ss    5
-#define	MDOC_Pp    6
-#define	MDOC_D1    7
-#define	MDOC_Dl    8
-#define	MDOC_Bd    9
-#define	MDOC_Ed   10
-#define	MDOC_Bl   11
-#define	MDOC_El   12
-#define	MDOC_It   13
-#define	MDOC_Ad   14
-#define	MDOC_An   15
-#define	MDOC_Ar   16
-#define	MDOC_Cd   17
-#define	MDOC_Cm   18
-#define	MDOC_Dv   19
-#define	MDOC_Er   20
-#define	MDOC_Ev   21
-#define	MDOC_Ex   22
-#define	MDOC_Fa   23
-#define	MDOC_Fd   24
-#define	MDOC_Fl   25
-#define	MDOC_Fn   26
-#define	MDOC_Ft   27
-#define	MDOC_Ic   28
-#define	MDOC_In   29
-#define	MDOC_Li   30
-#define	MDOC_Nd   31
-#define	MDOC_Nm   32
-#define	MDOC_Op   33
-#define	MDOC_Ot   34
-#define	MDOC_Pa   35
-#define	MDOC_Rv   36
-#define	MDOC_St   37
-#define	MDOC_Va   38
-#define	MDOC_Vt   39
-#define	MDOC_Xr   40
-#define	MDOC__A   41
-#define	MDOC__B   42
-#define	MDOC__D   43
-#define	MDOC__I   44
-#define	MDOC__J   45
-#define	MDOC__N   46
-#define	MDOC__O   47
-#define	MDOC__P   48
-#define	MDOC__R   49
-#define	MDOC__T   50
-#define	MDOC__V   51
-#define	MDOC_Ac   52
-#define	MDOC_Ao   53
-#define	MDOC_Aq   54
-#define	MDOC_At   55
-#define	MDOC_Bc   56
-#define	MDOC_Bf   57
-#define	MDOC_Bo   58
-#define	MDOC_Bq   59
-#define	MDOC_Bsx  60
-#define	MDOC_Bx   61
-#define	MDOC_Db   62
-#define	MDOC_Dc   63
-#define	MDOC_Do   64
-#define	MDOC_Dq   65
-#define	MDOC_Ec   66
-#define	MDOC_Ef   67
-#define	MDOC_Em   68
-#define	MDOC_Eo   69
-#define	MDOC_Fx   70
-#define	MDOC_Ms   71
-#define	MDOC_No   72
-#define	MDOC_Ns   73
-#define	MDOC_Nx   74
-#define	MDOC_Ox   75
-#define	MDOC_Pc   76
-#define	MDOC_Pf   77
-#define	MDOC_Po   78
-#define	MDOC_Pq   79
-#define	MDOC_Qc   80
-#define	MDOC_Ql   81
-#define	MDOC_Qo   82
-#define	MDOC_Qq   83
-#define	MDOC_Re   84
-#define	MDOC_Rs   85
-#define	MDOC_Sc   86
-#define	MDOC_So   87
-#define	MDOC_Sq   88
-#define	MDOC_Sm   89
-#define	MDOC_Sx   90
-#define	MDOC_Sy   91
-#define	MDOC_Tn   92
-#define	MDOC_Ux   93
-#define	MDOC_Xc   94
-#define	MDOC_Xo   95
-#define	MDOC_Fo   96
-#define	MDOC_Fc   97
-#define	MDOC_Oo   98
-#define	MDOC_Oc   99
-#define	MDOC_Bk  100
-#define	MDOC_Ek  101
-#define	MDOC_Bt  102
-#define	MDOC_Hf  103
-#define	MDOC_Fr  104
-#define	MDOC_Ud  105
-#define	MDOC_Lb  106
-#define	MDOC_Lp  107
-#define	MDOC_Lk  108
-#define	MDOC_Mt  109
-#define	MDOC_Brq 110
-#define	MDOC_Bro 111
-#define	MDOC_Brc 112
-#define	MDOC__C  113
-#define	MDOC_Es  114
-#define	MDOC_En  115
-#define	MDOC_Dx  116
-#define	MDOC__Q  117
-#define	MDOC_br  118
-#define	MDOC_sp  119
-#define	MDOC__U  120
-#define	MDOC_Ta  121
-#define	MDOC_ll  122
-#define	MDOC_MAX 123
-
 enum	mdocargt {
 	MDOC_Split, /* -split */
 	MDOC_Nosplit, /* -nospli */
@@ -274,11 +149,7 @@ union	mdoc_data {
 	struct mdoc_rs	  Rs;
 };
 
-/* Names of macros. */
-extern	const char *const *mdoc_macronames;
-
 /* Names of macro args.  Index is enum mdocargt. */
 extern	const char *const *mdoc_argnames;
-
 
 void		 mdoc_validate(struct roff_man *);
Index: man_macro.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man_macro.c,v
retrieving revision 1.115
retrieving revision 1.116
diff -Lman_macro.c -Lman_macro.c -u -p -r1.115 -r1.116
--- man_macro.c
+++ man_macro.c
@@ -1,7 +1,7 @@
 /*	$Id$ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012-2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
  *
  * Permission to use, copy, modify, and distribute this software for any
@@ -38,10 +38,9 @@ static	void		 blk_imp(MACRO_PROT_ARGS);
 static	void		 in_line_eoln(MACRO_PROT_ARGS);
 static	int		 man_args(struct roff_man *, int,
 				int *, char *, char **);
-static	void		 rew_scope(struct roff_man *, int);
+static	void		 rew_scope(struct roff_man *, enum roff_tok);
 
-const	struct man_macro __man_macros[MAN_MAX] = {
-	{ in_line_eoln, MAN_NSCOPED }, /* br */
+const	struct man_macro __man_macros[MAN_MAX - MAN_TH] = {
 	{ in_line_eoln, MAN_BSCOPE }, /* TH */
 	{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */
 	{ blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */
@@ -62,6 +61,7 @@ const	struct man_macro __man_macros[MAN_
 	{ in_line_eoln, MAN_SCOPED | MAN_JOIN }, /* I */
 	{ in_line_eoln, 0 }, /* IR */
 	{ in_line_eoln, 0 }, /* RI */
+	{ in_line_eoln, MAN_NSCOPED }, /* br */
 	{ in_line_eoln, MAN_NSCOPED }, /* sp */
 	{ in_line_eoln, MAN_NSCOPED }, /* nf */
 	{ in_line_eoln, MAN_NSCOPED }, /* fi */
@@ -80,8 +80,7 @@ const	struct man_macro __man_macros[MAN_
 	{ blk_close, MAN_BSCOPE }, /* UE */
 	{ in_line_eoln, 0 }, /* ll */
 };
-
-const	struct man_macro * const man_macros = __man_macros;
+const	struct man_macro *const man_macros = __man_macros - MAN_TH;
 
 
 void
@@ -100,8 +99,7 @@ man_unscope(struct roff_man *man, const 
 			    man_macros[n->tok].flags & MAN_SCOPED) {
 				mandoc_vmsg(MANDOCERR_BLK_LINE,
 				    man->parse, n->line, n->pos,
-				    "EOF breaks %s",
-				    man_macronames[n->tok]);
+				    "EOF breaks %s", roff_name[n->tok]);
 				if (man->flags & MAN_ELINE)
 					man->flags &= ~MAN_ELINE;
 				else {
@@ -118,7 +116,7 @@ man_unscope(struct roff_man *man, const 
 			    man_macros[n->tok].fp == blk_exp)
 				mandoc_msg(MANDOCERR_BLK_NOEND,
 				    man->parse, n->line, n->pos,
-				    man_macronames[n->tok]);
+				    roff_name[n->tok]);
 		}
 
 		/*
@@ -150,7 +148,7 @@ man_unscope(struct roff_man *man, const 
  * scopes.  When a scope is closed, it must be validated and actioned.
  */
 static void
-rew_scope(struct roff_man *man, int tok)
+rew_scope(struct roff_man *man, enum roff_tok tok)
 {
 	struct roff_node *n;
 
@@ -193,7 +191,7 @@ rew_scope(struct roff_man *man, int tok)
 void
 blk_close(MACRO_PROT_ARGS)
 {
-	int			 ntok;
+	enum roff_tok		 ntok;
 	const struct roff_node	*nn;
 	char			*p;
 	int			 nrew, target;
@@ -233,7 +231,7 @@ blk_close(MACRO_PROT_ARGS)
 
 	if (nn == NULL) {
 		mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse,
-		    line, ppos, man_macronames[tok]);
+		    line, ppos, roff_name[tok]);
 		rew_scope(man, MAN_PP);
 	} else {
 		line = man->last->line;
@@ -266,9 +264,8 @@ blk_exp(MACRO_PROT_ARGS)
 		roff_word_alloc(man, line, la, p);
 
 	if (buf[*pos] != '\0')
-		mandoc_vmsg(MANDOCERR_ARG_EXCESS,
-		    man->parse, line, *pos, "%s ... %s",
-		    man_macronames[tok], buf + *pos);
+		mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, line,
+		    *pos, "%s ... %s", roff_name[tok], buf + *pos);
 
 	man_unscope(man, head);
 	roff_body_alloc(man, line, ppos, tok);
@@ -335,14 +332,14 @@ in_line_eoln(MACRO_PROT_ARGS)
 		    tok == MAN_fi || tok == MAN_nf)) {
 			mandoc_vmsg(MANDOCERR_ARG_SKIP,
 			    man->parse, line, *pos, "%s %s",
-			    man_macronames[tok], buf + *pos);
+			    roff_name[tok], buf + *pos);
 			break;
 		}
 		if (buf[*pos] != '\0' && man->last != n &&
 		    (tok == MAN_PD || tok == MAN_ft || tok == MAN_sp)) {
 			mandoc_vmsg(MANDOCERR_ARG_EXCESS,
 			    man->parse, line, *pos, "%s ... %s",
-			    man_macronames[tok], buf + *pos);
+			    roff_name[tok], buf + *pos);
 			break;
 		}
 		la = *pos;
Index: man_html.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man_html.c,v
retrieving revision 1.135
retrieving revision 1.136
diff -Lman_html.c -Lman_html.c -u -p -r1.135 -r1.136
--- man_html.c
+++ man_html.c
@@ -71,8 +71,7 @@ static	int		  man_in_pre(MAN_ARGS);
 static	void		  man_root_post(MAN_ARGS);
 static	void		  man_root_pre(MAN_ARGS);
 
-static	const struct htmlman mans[MAN_MAX] = {
-	{ man_br_pre, NULL }, /* br */
+static	const struct htmlman __mans[MAN_MAX - MAN_TH] = {
 	{ NULL, NULL }, /* TH */
 	{ man_SH_pre, NULL }, /* SH */
 	{ man_SS_pre, NULL }, /* SS */
@@ -93,6 +92,7 @@ static	const struct htmlman mans[MAN_MAX
 	{ man_I_pre, NULL }, /* I */
 	{ man_alt_pre, NULL }, /* IR */
 	{ man_alt_pre, NULL }, /* RI */
+	{ man_br_pre, NULL }, /* br */
 	{ man_br_pre, NULL }, /* sp */
 	{ NULL, NULL }, /* nf */
 	{ NULL, NULL }, /* fi */
@@ -111,6 +111,7 @@ static	const struct htmlman mans[MAN_MAX
 	{ NULL, NULL }, /* UE */
 	{ man_ign_pre, NULL }, /* ll */
 };
+static	const struct htmlman *const mans = __mans - MAN_TH;
 
 
 /*
Index: libman.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/libman.h,v
retrieving revision 1.79
retrieving revision 1.80
diff -Llibman.h -Llibman.h -u -p -r1.79 -r1.80
--- libman.h
+++ libman.h
@@ -17,7 +17,7 @@
  */
 
 #define	MACRO_PROT_ARGS	  struct roff_man *man, \
-			  int tok, \
+			  enum roff_tok tok, \
 			  int line, \
 			  int ppos, \
 			  int *pos, \
@@ -35,7 +35,7 @@ struct	man_macro {
 extern	const struct man_macro *const man_macros;
 
 
-int		  man_hash_find(const char *);
+enum roff_tok	  man_hash_find(const char *);
 void		  man_node_validate(struct roff_man *);
 void		  man_state(struct roff_man *, struct roff_node *);
 void		  man_unscope(struct roff_man *, const struct roff_node *);
Index: mdoc_html.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_html.c,v
retrieving revision 1.279
retrieving revision 1.280
diff -Lmdoc_html.c -Lmdoc_html.c -u -p -r1.279 -r1.280
--- mdoc_html.c
+++ mdoc_html.c
@@ -118,8 +118,7 @@ static	int		  mdoc_vt_pre(MDOC_ARGS);
 static	int		  mdoc_xr_pre(MDOC_ARGS);
 static	int		  mdoc_xx_pre(MDOC_ARGS);
 
-static	const struct htmlmdoc mdocs[MDOC_MAX] = {
-	{mdoc_ap_pre, NULL}, /* Ap */
+static	const struct htmlmdoc __mdocs[MDOC_MAX - MDOC_Dd] = {
 	{NULL, NULL}, /* Dd */
 	{NULL, NULL}, /* Dt */
 	{NULL, NULL}, /* Os */
@@ -135,6 +134,7 @@ static	const struct htmlmdoc mdocs[MDOC_
 	{mdoc_it_pre, NULL}, /* It */
 	{mdoc_ad_pre, NULL}, /* Ad */
 	{mdoc_an_pre, NULL}, /* An */
+	{mdoc_ap_pre, NULL}, /* Ap */
 	{mdoc_ar_pre, NULL}, /* Ar */
 	{mdoc_cd_pre, NULL}, /* Cd */
 	{mdoc_cm_pre, NULL}, /* Cm */
@@ -243,6 +243,7 @@ static	const struct htmlmdoc mdocs[MDOC_
 	{NULL, NULL}, /* Ta */
 	{mdoc_skip_pre, NULL}, /* ll */
 };
+static	const struct htmlmdoc *const mdocs = __mdocs - MDOC_Dd;
 
 
 /*
@@ -393,7 +394,9 @@ print_mdoc_node(MDOC_ARGS)
 			t = h->tag;
 		}
 		assert(h->tblt == NULL);
-		if (mdocs[n->tok].pre && (n->end == ENDBODY_NOT || n->child))
+		assert(n->tok >= MDOC_Dd && n->tok < MDOC_MAX);
+		if (mdocs[n->tok].pre != NULL &&
+		    (n->end == ENDBODY_NOT || n->child != NULL))
 			child = (*mdocs[n->tok].pre)(meta, n, h);
 		break;
 	}
@@ -412,7 +415,7 @@ print_mdoc_node(MDOC_ARGS)
 	case ROFFT_EQN:
 		break;
 	default:
-		if ( ! mdocs[n->tok].post || n->flags & NODE_ENDED)
+		if (mdocs[n->tok].post == NULL || n->flags & NODE_ENDED)
 			break;
 		(*mdocs[n->tok].post)(meta, n, h);
 		if (n->end != ENDBODY_NOT)
Index: man.h
===================================================================
RCS file: /home/cvs/mdocml/mdocml/man.h,v
retrieving revision 1.77
retrieving revision 1.78
diff -Lman.h -Lman.h -u -p -r1.77 -r1.78
--- man.h
+++ man.h
@@ -16,50 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define	MAN_br   0
-#define	MAN_TH   1
-#define	MAN_SH   2
-#define	MAN_SS   3
-#define	MAN_TP   4
-#define	MAN_LP   5
-#define	MAN_PP   6
-#define	MAN_P    7
-#define	MAN_IP   8
-#define	MAN_HP   9
-#define	MAN_SM  10
-#define	MAN_SB  11
-#define	MAN_BI  12
-#define	MAN_IB  13
-#define	MAN_BR  14
-#define	MAN_RB  15
-#define	MAN_R   16
-#define	MAN_B   17
-#define	MAN_I   18
-#define	MAN_IR  19
-#define	MAN_RI  20
-#define	MAN_sp  21
-#define	MAN_nf  22
-#define	MAN_fi  23
-#define	MAN_RE  24
-#define	MAN_RS  25
-#define	MAN_DT  26
-#define	MAN_UC  27
-#define	MAN_PD  28
-#define	MAN_AT  29
-#define	MAN_in  30
-#define	MAN_ft  31
-#define	MAN_OP  32
-#define	MAN_EX  33
-#define	MAN_EE  34
-#define	MAN_UR  35
-#define	MAN_UE  36
-#define	MAN_ll  37
-#define	MAN_MAX 38
-
-/* Names of macros. */
-extern	const char *const *man_macronames;
-
-
 struct	roff_man;
 
 const struct mparse	*man_mparse(const struct roff_man *);
Index: mdoc_state.c
===================================================================
RCS file: /home/cvs/mdocml/mdocml/mdoc_state.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -Lmdoc_state.c -Lmdoc_state.c -u -p -r1.4 -r1.5
--- mdoc_state.c
+++ mdoc_state.c
@@ -1,6 +1,6 @@
 /*	$Id$ */
 /*
- * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2014, 2015, 2017 Ingo Schwarze <schwarze@openbsd.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -35,8 +35,7 @@ static	void	 state_dl(STATE_ARGS);
 static	void	 state_sh(STATE_ARGS);
 static	void	 state_sm(STATE_ARGS);
 
-static	const state_handler state_handlers[MDOC_MAX] = {
-	NULL,		/* Ap */
+static	const state_handler __state_handlers[MDOC_MAX - MDOC_Dd] = {
 	NULL,		/* Dd */
 	NULL,		/* Dt */
 	NULL,		/* Os */
@@ -52,6 +51,7 @@ static	const state_handler state_handler
 	NULL,		/* It */
 	NULL,		/* Ad */
 	NULL,		/* An */
+	NULL,		/* Ap */
 	NULL,		/* Ar */
 	NULL,		/* Cd */
 	NULL,		/* Cm */
@@ -160,6 +160,7 @@ static	const state_handler state_handler
 	NULL,		/* Ta */
 	NULL,		/* ll */
 };
+static const state_handler *const state_handlers = __state_handlers - MDOC_Dd;
 
 
 void
--
 To unsubscribe send an email to source+unsubscribe@mdocml.bsd.lv

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2017-04-24 23:06 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-24 23:06 mdocml: Continue parser unification: * Make enum rofft an internal schwarze

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).