diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | Makefile.depend | 7 | ||||
-rw-r--r-- | libman.h | 1 | ||||
-rw-r--r-- | libmandoc.h | 2 | ||||
-rw-r--r-- | libmdoc.h | 1 | ||||
-rw-r--r-- | man.c | 27 | ||||
-rw-r--r-- | man_hash.c | 101 | ||||
-rw-r--r-- | mandoc_headers.3 | 29 | ||||
-rw-r--r-- | mdoc.c | 25 | ||||
-rw-r--r-- | mdoc_hash.c | 95 | ||||
-rw-r--r-- | mdoc_macro.c | 2 | ||||
-rw-r--r-- | mdoc_validate.c | 14 | ||||
-rw-r--r-- | read.c | 17 | ||||
-rw-r--r-- | roff.c | 600 | ||||
-rw-r--r-- | roff.h | 7 |
15 files changed, 368 insertions, 564 deletions
@@ -85,7 +85,6 @@ SRCS = att.c \ lib.c \ main.c \ man.c \ - man_hash.c \ man_html.c \ man_macro.c \ man_term.c \ @@ -99,7 +98,6 @@ SRCS = att.c \ mansearch.c \ mdoc.c \ mdoc_argv.c \ - mdoc_hash.c \ mdoc_html.c \ mdoc_macro.c \ mdoc_man.c \ @@ -198,7 +196,6 @@ DISTFILES = INSTALL \ $(TESTSRCS) LIBMAN_OBJS = man.o \ - man_hash.o \ man_macro.o \ man_validate.o @@ -206,7 +203,6 @@ LIBMDOC_OBJS = att.o \ lib.o \ mdoc.o \ mdoc_argv.o \ - mdoc_hash.o \ mdoc_macro.o \ mdoc_state.o \ mdoc_validate.o \ diff --git a/Makefile.depend b/Makefile.depend index 8827f0ce..b8e5363b 100644 --- a/Makefile.depend +++ b/Makefile.depend @@ -28,11 +28,10 @@ demandoc.o: demandoc.c config.h roff.h man.h mdoc.h mandoc.h eqn.o: eqn.c config.h mandoc.h mandoc_aux.h libmandoc.h libroff.h eqn_html.o: eqn_html.c config.h mandoc.h out.h html.h eqn_term.o: eqn_term.c config.h mandoc.h out.h term.h -html.o: html.c config.h mandoc.h mandoc_aux.h out.h html.h manconf.h main.h +html.o: html.c config.h mandoc_aux.h mandoc.h roff.h out.h html.h manconf.h main.h lib.o: lib.c config.h roff.h mdoc.h libmdoc.h lib.in main.o: main.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h tag.h main.h manconf.h mansearch.h man.o: man.c config.h mandoc_aux.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h -man_hash.o: man_hash.c config.h mandoc.h roff.h man.h libmandoc.h libman.h man_html.o: man_html.c config.h mandoc_aux.h roff.h man.h out.h html.h main.h man_macro.o: man_macro.c config.h mandoc.h roff.h man.h libmandoc.h roff_int.h libman.h man_term.o: man_term.c config.h mandoc_aux.h mandoc.h roff.h man.h out.h term.h main.h @@ -46,10 +45,10 @@ manpath.o: manpath.c config.h mandoc_aux.h manconf.h mansearch.o: mansearch.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h manconf.h mansearch.h dbm.h mdoc.o: mdoc.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h mdoc_argv.o: mdoc_argv.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h -mdoc_hash.o: mdoc_hash.c config.h mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h mdoc_html.o: mdoc_html.c config.h mandoc_aux.h roff.h mdoc.h out.h html.h main.h mdoc_macro.o: mdoc_macro.c config.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h mdoc_man.o: mdoc_man.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h out.h main.h +mdoc_markdown.o: mdoc_markdown.c mandoc_aux.h mandoc.h roff.h mdoc.h main.h mdoc_state.o: mdoc_state.c mandoc.h roff.h mdoc.h libmandoc.h libmdoc.h mdoc_term.o: mdoc_term.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h out.h term.h tag.h main.h mdoc_validate.o: mdoc_validate.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h libmandoc.h roff_int.h libmdoc.h @@ -57,7 +56,7 @@ msec.o: msec.c config.h mandoc.h libmandoc.h msec.in out.o: out.c config.h mandoc_aux.h mandoc.h out.h preconv.o: preconv.c config.h mandoc.h libmandoc.h read.o: read.c config.h mandoc_aux.h mandoc.h roff.h mdoc.h man.h libmandoc.h roff_int.h -roff.o: roff.c config.h mandoc.h mandoc_aux.h roff.h libmandoc.h roff_int.h libroff.h predefs.in +roff.o: roff.c config.h mandoc.h mandoc_aux.h mandoc_ohash.h compat_ohash.h roff.h libmandoc.h roff_int.h libroff.h predefs.in soelim.o: soelim.c config.h compat_stringlist.h st.o: st.c config.h roff.h mdoc.h libmdoc.h st.in tag.o: tag.c config.h mandoc_aux.h mandoc_ohash.h compat_ohash.h tag.h @@ -35,7 +35,6 @@ struct man_macro { extern const struct man_macro *const man_macros; -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 *); diff --git a/libmandoc.h b/libmandoc.h index 53f764c6..c0d71552 100644 --- a/libmandoc.h +++ b/libmandoc.h @@ -50,11 +50,9 @@ int mandoc_eos(const char *, size_t); int mandoc_strntoi(const char *, size_t, int); const char *mandoc_a2msec(const char*); -void mdoc_hash_init(void); int mdoc_parseln(struct roff_man *, int, char *, int); void mdoc_endparse(struct roff_man *); -void man_hash_init(void); int man_parseln(struct roff_man *, int, char *, int); void man_endparse(struct roff_man *); @@ -76,7 +76,6 @@ 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 *); -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 *); @@ -145,26 +145,19 @@ man_pmacro(struct roff_man *man, int ln, char *buf, int offs) { struct roff_node *n; const char *cp; - int tok; - int i, ppos; + size_t sz; + enum roff_tok tok; + int ppos; int bline; - char mac[5]; - ppos = offs; - - /* - * Copy the first word into a nil-terminated buffer. - * Stop when a space, tab, escape, or eoln is encountered. - */ - - i = 0; - while (i < 4 && strchr(" \t\\", buf[offs]) == NULL) - mac[i++] = buf[offs++]; - - mac[i] = '\0'; - - tok = (i > 0 && i < 4) ? man_hash_find(mac) : TOKEN_NONE; + /* Determine the line macro. */ + ppos = offs; + tok = TOKEN_NONE; + for (sz = 0; sz < 4 && strchr(" \t\\", buf[offs]) == NULL; sz++) + offs++; + if (sz > 0 && sz < 4) + tok = roffhash_find(man->manmac, buf + ppos, sz); if (tok == TOKEN_NONE) { mandoc_msg(MANDOCERR_MACRO, man->parse, ln, ppos, buf + ppos - 1); diff --git a/man_hash.c b/man_hash.c deleted file mode 100644 index 2466eb73..00000000 --- a/man_hash.c +++ /dev/null @@ -1,101 +0,0 @@ -/* $Id$ */ -/* - * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> - * 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 - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "config.h" - -#include <sys/types.h> - -#include <assert.h> -#include <ctype.h> -#include <limits.h> -#include <string.h> - -#include "mandoc.h" -#include "roff.h" -#include "man.h" -#include "libmandoc.h" -#include "libman.h" - -#define HASH_DEPTH 6 - -#define HASH_ROW(x) do { \ - if (isupper((unsigned char)(x))) \ - (x) -= 65; \ - else \ - (x) -= 97; \ - (x) *= HASH_DEPTH; \ - } while (/* CONSTCOND */ 0) - -/* - * Lookup table is indexed first by lower-case first letter (plus one - * for the period, which is stored in the last row), then by lower or - * uppercase second letter. Buckets correspond to the index of the - * macro (the integer value of the enum stored as a char to save a bit - * of space). - */ -static unsigned char table[26 * HASH_DEPTH]; - - -void -man_hash_init(void) -{ - int i, j, x; - - if (*table != '\0') - return; - - memset(table, UCHAR_MAX, sizeof(table)); - - for (i = 0; i < (int)(MAN_MAX - MAN_TH); i++) { - x = *roff_name[MAN_TH + i]; - - assert(isalpha((unsigned char)x)); - - HASH_ROW(x); - - for (j = 0; j < HASH_DEPTH; j++) - if (UCHAR_MAX == table[x + j]) { - table[x + j] = (unsigned char)i; - break; - } - - assert(j < HASH_DEPTH); - } -} - -enum roff_tok -man_hash_find(const char *tmp) -{ - int x, y, i; - - if ('\0' == (x = tmp[0])) - return TOKEN_NONE; - if ( ! (isalpha((unsigned char)x))) - return TOKEN_NONE; - - HASH_ROW(x); - - for (i = 0; i < HASH_DEPTH; i++) { - if (UCHAR_MAX == (y = table[x + i])) - return TOKEN_NONE; - - if (strcmp(tmp, roff_name[MAN_TH + y]) == 0) - return MAN_TH + y; - } - - return TOKEN_NONE; -} diff --git a/mandoc_headers.3 b/mandoc_headers.3 index 3f93a804..96100f21 100644 --- a/mandoc_headers.3 +++ b/mandoc_headers.3 @@ -60,9 +60,19 @@ Requires .In sys/types.h for .Vt size_t . +.Pp Provides the utility functions documented in .Xr mandoc_malloc 3 . .It Qq Pa mandoc_ohash.h +Requires +.In stddef.h +for +.Vt ptrdiff_t +and +.In stdint.h +for +.Vt uint32_t . +.Pp Includes .In ohash.h and provides @@ -113,6 +123,11 @@ from .Pa roff.h as an opaque type for function prototypes. .It Qq Pa roff.h +Requires +.Qq Pa mandoc_ohash.h +for +.Vt struct ohash . +.Pp Provides .Vt enum mdoc_endbody , .Vt enum roff_macroset , @@ -125,8 +140,12 @@ Provides .Vt struct roff_node , the constant array .Va roff_name -and the function -.Fn deroff . +and the functions +.Fn deroff , +.Fn roffhash_alloc , +.Fn roffhash_find , +and +.Fn roffhash_free . .Pp Uses pointers to the types .Vt struct mdoc_arg @@ -315,6 +334,7 @@ Requires .Qq Pa roff.h for .Vt enum roff_tok . +.Pp Provides .Vt struct man_macro and some functions internal to the @@ -443,10 +463,7 @@ or Requires .In sys/types.h for -.Vt size_t , -.In stdio.h -for -.Dv BUFSIZ , +.Vt size_t and .Qq Pa out.h for @@ -302,25 +302,18 @@ mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs) { struct roff_node *n; const char *cp; + size_t sz; enum roff_tok tok; - int i, sv; - char mac[5]; + int sv; - sv = offs; - - /* - * Copy the first word into a nil-terminated buffer. - * Stop when a space, tab, escape, or eoln is encountered. - */ - - i = 0; - while (i < 4 && strchr(" \t\\", buf[offs]) == NULL) - mac[i++] = buf[offs++]; - - mac[i] = '\0'; - - tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : TOKEN_NONE; + /* Determine the line macro. */ + sv = offs; + tok = TOKEN_NONE; + for (sz = 0; sz < 4 && strchr(" \t\\", buf[offs]) == NULL; sz++) + offs++; + if (sz == 2 || sz == 3) + tok = roffhash_find(mdoc->mdocmac, buf + sv, sz); if (tok == TOKEN_NONE) { mandoc_msg(MANDOCERR_MACRO, mdoc->parse, ln, sv, buf + sv - 1); diff --git a/mdoc_hash.c b/mdoc_hash.c deleted file mode 100644 index 37ac4425..00000000 --- a/mdoc_hash.c +++ /dev/null @@ -1,95 +0,0 @@ -/* $Id$ */ -/* - * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> - * 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 - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "config.h" - -#include <sys/types.h> - -#include <assert.h> -#include <ctype.h> -#include <limits.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "mandoc.h" -#include "roff.h" -#include "mdoc.h" -#include "libmandoc.h" -#include "libmdoc.h" - -static unsigned char table[27 * 12]; - - -void -mdoc_hash_init(void) -{ - int i, j, major; - const char *p; - - if (*table != '\0') - return; - - memset(table, UCHAR_MAX, sizeof(table)); - - 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); - else - major = 12 * 26; - - for (j = 0; j < 12; j++) - if (UCHAR_MAX == table[major + j]) { - table[major + j] = (unsigned char)i; - break; - } - - assert(j < 12); - } -} - -enum roff_tok -mdoc_hash_find(const char *p) -{ - int major, i, j; - - if (0 == p[0]) - return TOKEN_NONE; - if ( ! isalpha((unsigned char)p[0]) && '%' != p[0]) - return TOKEN_NONE; - - if (isalpha((unsigned char)p[1])) - major = 12 * (tolower((unsigned char)p[1]) - 97); - else if ('1' == p[1]) - major = 12 * 26; - else - return TOKEN_NONE; - - if (p[2] && p[3]) - return TOKEN_NONE; - - for (j = 0; j < 12; j++) { - if (UCHAR_MAX == (i = table[major + j])) - break; - if (strcmp(p, roff_name[MDOC_Dd + i]) == 0) - return MDOC_Dd + i; - } - - return TOKEN_NONE; -} diff --git a/mdoc_macro.c b/mdoc_macro.c index 3b351888..b7c29e7c 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -247,7 +247,7 @@ lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p) return TOKEN_NONE; } if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) { - res = mdoc_hash_find(p); + res = roffhash_find(mdoc->mdocmac, p, 0); if (res != TOKEN_NONE) { if (mdoc_macros[res].flags & MDOC_CALLABLE) return res; diff --git a/mdoc_validate.c b/mdoc_validate.c index 554520bc..ed1c8017 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -58,7 +58,7 @@ static void check_argv(struct roff_man *, static void check_args(struct roff_man *, struct roff_node *); static int child_an(const struct roff_node *); static size_t macro2len(enum roff_tok); -static void rewrite_macro2len(char **); +static void rewrite_macro2len(struct roff_man *, char **); static void post_an(POST_ARGS); static void post_an_norm(POST_ARGS); @@ -451,7 +451,7 @@ post_bl_norm(POST_ARGS) mdoc->parse, argv->line, argv->pos, "Bl -width %s", argv->value[0]); - rewrite_macro2len(argv->value); + rewrite_macro2len(mdoc, argv->value); n->norm->Bl.width = argv->value[0]; break; case MDOC_Offset: @@ -466,7 +466,7 @@ post_bl_norm(POST_ARGS) mdoc->parse, argv->line, argv->pos, "Bl -offset %s", argv->value[0]); - rewrite_macro2len(argv->value); + rewrite_macro2len(mdoc, argv->value); n->norm->Bl.offs = argv->value[0]; break; default: @@ -593,7 +593,7 @@ post_bd(POST_ARGS) mdoc->parse, argv->line, argv->pos, "Bd -offset %s", argv->value[0]); - rewrite_macro2len(argv->value); + rewrite_macro2len(mdoc, argv->value); n->norm->Bd.offs = argv->value[0]; break; case MDOC_Compact: @@ -1338,8 +1338,8 @@ post_bl_block(POST_ARGS) * If the argument of -offset or -width is a macro, * replace it with the associated default width. */ -void -rewrite_macro2len(char **arg) +static void +rewrite_macro2len(struct roff_man *mdoc, char **arg) { size_t width; enum roff_tok tok; @@ -1348,7 +1348,7 @@ rewrite_macro2len(char **arg) return; else if ( ! strcmp(*arg, "Ds")) width = 6; - else if ((tok = mdoc_hash_find(*arg)) == TOKEN_NONE) + else if ((tok = roffhash_find(mdoc->mdocmac, *arg, 0)) == TOKEN_NONE) return; else width = macro2len(tok); @@ -293,14 +293,15 @@ choose_parser(struct mparse *curp) } if (format == MPARSE_MDOC) { - mdoc_hash_init(); curp->man->macroset = MACROSET_MDOC; - curp->man->first->tok = TOKEN_NONE; + if (curp->man->mdocmac == NULL) + curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX); } else { - man_hash_init(); curp->man->macroset = MACROSET_MAN; - curp->man->first->tok = TOKEN_NONE; + if (curp->man->manmac == NULL) + curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX); } + curp->man->first->tok = TOKEN_NONE; } /* @@ -818,11 +819,13 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg, curp->man = roff_man_alloc( curp->roff, curp, curp->defos, curp->options & MPARSE_QUICK ? 1 : 0); if (curp->options & MPARSE_MDOC) { - mdoc_hash_init(); curp->man->macroset = MACROSET_MDOC; + if (curp->man->mdocmac == NULL) + curp->man->mdocmac = roffhash_alloc(MDOC_Dd, MDOC_MAX); } else if (curp->options & MPARSE_MAN) { - man_hash_init(); curp->man->macroset = MACROSET_MAN; + if (curp->man->manmac == NULL) + curp->man->manmac = roffhash_alloc(MAN_TH, MAN_MAX); } curp->man->first->tok = TOKEN_NONE; return curp; @@ -848,6 +851,8 @@ void mparse_free(struct mparse *curp) { + roffhash_free(curp->man->mdocmac); + roffhash_free(curp->man->manmac); roff_man_free(curp->man); roff_free(curp->roff); if (curp->secondary) @@ -22,12 +22,15 @@ #include <assert.h> #include <ctype.h> #include <limits.h> +#include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "mandoc.h" #include "mandoc_aux.h" +#include "mandoc_ohash.h" #include "roff.h" #include "libmandoc.h" #include "roff_int.h" @@ -64,10 +67,19 @@ struct roffreg { struct roffreg *next; }; +/* + * Association of request and macro names with token IDs. + */ +struct roffreq { + enum roff_tok tok; + char name[]; +}; + struct roff { struct mparse *parse; /* parse point */ struct roffnode *last; /* leaf of stack */ int *rstack; /* stack of inverted `ie' values */ + struct ohash *reqtab; /* request lookup table */ struct roffreg *regtab; /* number registers */ struct roffkv *strtab; /* user-defined strings & macros */ struct roffkv *xmbtab; /* multi-byte trans table (`tr') */ @@ -110,13 +122,11 @@ struct roffnode { typedef enum rofferr (*roffproc)(ROFF_ARGS); struct roffmac { - const char *name; /* macro name */ roffproc proc; /* process new macro */ roffproc text; /* process as child text of macro */ roffproc sub; /* process as child of macro */ int flags; #define ROFFMAC_STRUCT (1 << 0) /* always interpret */ - struct roffmac *next; }; struct predef { @@ -129,8 +139,6 @@ struct predef { /* --- function prototypes ------------------------------------------------ */ -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 roff_tok, @@ -197,12 +205,6 @@ static enum rofferr roff_userdef(ROFF_ARGS); /* --- constant data ------------------------------------------------------ */ -/* See roffhash_find() */ - -#define ASCII_HI 126 -#define ASCII_LO 33 -#define HASHWIDTH (ASCII_HI - ASCII_LO + 1) - #define ROFFNUM_SCALE (1 << 0) /* Honour scaling in roff_getnum(). */ #define ROFFNUM_WHITE (1 << 1) /* Skip whitespace in roff_evalnum(). */ @@ -311,245 +313,243 @@ const char *__roff_name[MAN_MAX + 1] = { }; const char *const *roff_name = __roff_name; -static struct roffmac *hash[HASHWIDTH]; - 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 }, - { "aln", roff_unsupp, NULL, NULL, 0, NULL }, - { "als", roff_unsupp, NULL, NULL, 0, NULL }, - { "am", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "am1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "ami", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "ami1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "as", roff_ds, NULL, NULL, 0, NULL }, - { "as1", roff_ds, NULL, NULL, 0, NULL }, - { "asciify", roff_unsupp, NULL, NULL, 0, NULL }, - { "backtrace", roff_line_ignore, NULL, NULL, 0, NULL }, - { "bd", roff_line_ignore, NULL, NULL, 0, NULL }, - { "bleedat", roff_line_ignore, NULL, NULL, 0, NULL }, - { "blm", roff_unsupp, NULL, NULL, 0, NULL }, - { "box", roff_unsupp, NULL, NULL, 0, NULL }, - { "boxa", roff_unsupp, NULL, NULL, 0, NULL }, - { "bp", roff_line_ignore, NULL, NULL, 0, NULL }, - { "BP", roff_unsupp, NULL, NULL, 0, NULL }, - { "break", roff_unsupp, NULL, NULL, 0, NULL }, - { "breakchar", roff_line_ignore, NULL, NULL, 0, NULL }, - { "brnl", roff_line_ignore, NULL, NULL, 0, NULL }, - { "brp", roff_brp, NULL, NULL, 0, NULL }, - { "brpnl", roff_line_ignore, NULL, NULL, 0, NULL }, - { "c2", roff_unsupp, NULL, NULL, 0, NULL }, - { "cc", roff_cc, NULL, NULL, 0, NULL }, - { "ce", roff_line_ignore, NULL, NULL, 0, NULL }, - { "cf", roff_insec, NULL, NULL, 0, NULL }, - { "cflags", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ch", roff_line_ignore, NULL, NULL, 0, NULL }, - { "char", roff_unsupp, NULL, NULL, 0, NULL }, - { "chop", roff_unsupp, NULL, NULL, 0, NULL }, - { "class", roff_line_ignore, NULL, NULL, 0, NULL }, - { "close", roff_insec, NULL, NULL, 0, NULL }, - { "CL", roff_unsupp, NULL, NULL, 0, NULL }, - { "color", roff_line_ignore, NULL, NULL, 0, NULL }, - { "composite", roff_unsupp, NULL, NULL, 0, NULL }, - { "continue", roff_unsupp, NULL, NULL, 0, NULL }, - { "cp", roff_line_ignore, NULL, NULL, 0, NULL }, - { "cropat", roff_line_ignore, NULL, NULL, 0, NULL }, - { "cs", roff_line_ignore, NULL, NULL, 0, NULL }, - { "cu", roff_line_ignore, NULL, NULL, 0, NULL }, - { "da", roff_unsupp, NULL, NULL, 0, NULL }, - { "dch", roff_unsupp, NULL, NULL, 0, NULL }, - { "Dd", roff_Dd, NULL, NULL, 0, NULL }, - { "de", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "defcolor", roff_line_ignore, NULL, NULL, 0, NULL }, - { "dei", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "dei1", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "device", roff_unsupp, NULL, NULL, 0, NULL }, - { "devicem", roff_unsupp, NULL, NULL, 0, NULL }, - { "di", roff_unsupp, NULL, NULL, 0, NULL }, - { "do", roff_unsupp, NULL, NULL, 0, NULL }, - { "ds", roff_ds, NULL, NULL, 0, NULL }, - { "ds1", roff_ds, NULL, NULL, 0, NULL }, - { "dwh", roff_unsupp, NULL, NULL, 0, NULL }, - { "dt", roff_unsupp, NULL, NULL, 0, NULL }, - { "ec", roff_unsupp, NULL, NULL, 0, NULL }, - { "ecr", roff_unsupp, NULL, NULL, 0, NULL }, - { "ecs", roff_unsupp, NULL, NULL, 0, NULL }, - { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, - { "em", roff_unsupp, NULL, NULL, 0, NULL }, - { "EN", roff_EN, NULL, NULL, 0, NULL }, - { "eo", roff_unsupp, NULL, NULL, 0, NULL }, - { "EP", roff_unsupp, NULL, NULL, 0, NULL }, - { "EQ", roff_EQ, NULL, NULL, 0, NULL }, - { "errprint", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ev", roff_unsupp, NULL, NULL, 0, NULL }, - { "evc", roff_unsupp, NULL, NULL, 0, NULL }, - { "ex", roff_unsupp, NULL, NULL, 0, NULL }, - { "fallback", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fam", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fc", roff_unsupp, NULL, NULL, 0, NULL }, - { "fchar", roff_unsupp, NULL, NULL, 0, NULL }, - { "fcolor", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fdeferlig", roff_line_ignore, NULL, NULL, 0, NULL }, - { "feature", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fkern", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fl", roff_line_ignore, NULL, NULL, 0, NULL }, - { "flig", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fp", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fps", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fschar", roff_unsupp, NULL, NULL, 0, NULL }, - { "fspacewidth", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fspecial", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ftr", roff_line_ignore, NULL, NULL, 0, NULL }, - { "fzoom", roff_line_ignore, NULL, NULL, 0, NULL }, - { "gcolor", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hc", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hcode", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hidechar", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hla", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hlm", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hpf", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hpfa", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hpfcode", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hw", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hy", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hylang", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hylen", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hym", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hypp", roff_line_ignore, NULL, NULL, 0, NULL }, - { "hys", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, - { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL }, - { "ig", roff_block, roff_block_text, roff_block_sub, 0, NULL }, - { "index", roff_unsupp, NULL, NULL, 0, NULL }, - { "it", roff_it, NULL, NULL, 0, NULL }, - { "itc", roff_unsupp, NULL, NULL, 0, NULL }, - { "IX", roff_line_ignore, NULL, NULL, 0, NULL }, - { "kern", roff_line_ignore, NULL, NULL, 0, NULL }, - { "kernafter", roff_line_ignore, NULL, NULL, 0, NULL }, - { "kernbefore", roff_line_ignore, NULL, NULL, 0, NULL }, - { "kernpair", roff_line_ignore, NULL, NULL, 0, NULL }, - { "lc", roff_unsupp, NULL, NULL, 0, NULL }, - { "lc_ctype", roff_unsupp, NULL, NULL, 0, NULL }, - { "lds", roff_unsupp, NULL, NULL, 0, NULL }, - { "length", roff_unsupp, NULL, NULL, 0, NULL }, - { "letadj", roff_line_ignore, NULL, NULL, 0, NULL }, - { "lf", roff_insec, NULL, NULL, 0, NULL }, - { "lg", roff_line_ignore, NULL, NULL, 0, NULL }, - { "lhang", roff_line_ignore, NULL, NULL, 0, NULL }, - { "linetabs", roff_unsupp, NULL, NULL, 0, NULL }, - { "lnr", roff_unsupp, NULL, NULL, 0, NULL }, - { "lnrf", roff_unsupp, NULL, NULL, 0, NULL }, - { "lpfx", roff_unsupp, NULL, NULL, 0, NULL }, - { "ls", roff_line_ignore, NULL, NULL, 0, NULL }, - { "lsm", roff_unsupp, NULL, NULL, 0, NULL }, - { "lt", roff_line_ignore, NULL, NULL, 0, NULL }, - { "mc", roff_line_ignore, NULL, NULL, 0, NULL }, - { "mediasize", roff_line_ignore, NULL, NULL, 0, NULL }, - { "minss", roff_line_ignore, NULL, NULL, 0, NULL }, - { "mk", roff_line_ignore, NULL, NULL, 0, NULL }, - { "mso", roff_insec, NULL, NULL, 0, NULL }, - { "na", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ne", roff_line_ignore, NULL, NULL, 0, NULL }, - { "nh", roff_line_ignore, NULL, NULL, 0, NULL }, - { "nhychar", roff_line_ignore, NULL, NULL, 0, NULL }, - { "nm", roff_unsupp, NULL, NULL, 0, NULL }, - { "nn", roff_unsupp, NULL, NULL, 0, NULL }, - { "nop", roff_unsupp, NULL, NULL, 0, NULL }, - { "nr", roff_nr, NULL, NULL, 0, NULL }, - { "nrf", roff_unsupp, NULL, NULL, 0, NULL }, - { "nroff", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ns", roff_line_ignore, NULL, NULL, 0, NULL }, - { "nx", roff_insec, NULL, NULL, 0, NULL }, - { "open", roff_insec, NULL, NULL, 0, NULL }, - { "opena", roff_insec, NULL, NULL, 0, NULL }, - { "os", roff_line_ignore, NULL, NULL, 0, NULL }, - { "output", roff_unsupp, NULL, NULL, 0, NULL }, - { "padj", roff_line_ignore, NULL, NULL, 0, NULL }, - { "papersize", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pc", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pev", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pi", roff_insec, NULL, NULL, 0, NULL }, - { "PI", roff_unsupp, NULL, NULL, 0, NULL }, - { "pl", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pm", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pn", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pnr", roff_line_ignore, NULL, NULL, 0, NULL }, - { "po", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ps", roff_line_ignore, NULL, NULL, 0, NULL }, - { "psbb", roff_unsupp, NULL, NULL, 0, NULL }, - { "pshape", roff_unsupp, NULL, NULL, 0, NULL }, - { "pso", roff_insec, NULL, NULL, 0, NULL }, - { "ptr", roff_line_ignore, NULL, NULL, 0, NULL }, - { "pvs", roff_line_ignore, NULL, NULL, 0, NULL }, - { "rchar", roff_unsupp, NULL, NULL, 0, NULL }, - { "rd", roff_line_ignore, NULL, NULL, 0, NULL }, - { "recursionlimit", roff_line_ignore, NULL, NULL, 0, NULL }, - { "return", roff_unsupp, NULL, NULL, 0, NULL }, - { "rfschar", roff_unsupp, NULL, NULL, 0, NULL }, - { "rhang", roff_line_ignore, NULL, NULL, 0, NULL }, - { "rj", roff_line_ignore, NULL, NULL, 0, NULL }, - { "rm", roff_rm, NULL, NULL, 0, NULL }, - { "rn", roff_unsupp, NULL, NULL, 0, NULL }, - { "rnn", roff_unsupp, NULL, NULL, 0, NULL }, - { "rr", roff_rr, NULL, NULL, 0, NULL }, - { "rs", roff_line_ignore, NULL, NULL, 0, NULL }, - { "rt", roff_line_ignore, NULL, NULL, 0, NULL }, - { "schar", roff_unsupp, NULL, NULL, 0, NULL }, - { "sentchar", roff_line_ignore, NULL, NULL, 0, NULL }, - { "shc", roff_line_ignore, NULL, NULL, 0, NULL }, - { "shift", roff_unsupp, NULL, NULL, 0, NULL }, - { "sizes", roff_line_ignore, NULL, NULL, 0, NULL }, - { "so", roff_so, NULL, NULL, 0, NULL }, - { "spacewidth", roff_line_ignore, NULL, NULL, 0, NULL }, - { "special", roff_line_ignore, NULL, NULL, 0, NULL }, - { "spreadwarn", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ss", roff_line_ignore, NULL, NULL, 0, NULL }, - { "sty", roff_line_ignore, NULL, NULL, 0, NULL }, - { "substring", roff_unsupp, NULL, NULL, 0, NULL }, - { "sv", roff_line_ignore, NULL, NULL, 0, NULL }, - { "sy", roff_insec, NULL, NULL, 0, NULL }, - { "T&", roff_T_, NULL, NULL, 0, NULL }, - { "ta", roff_unsupp, NULL, NULL, 0, NULL }, - { "tc", roff_unsupp, NULL, NULL, 0, NULL }, - { "TE", roff_TE, NULL, NULL, 0, NULL }, - { "TH", roff_TH, NULL, NULL, 0, NULL }, - { "ti", roff_unsupp, NULL, NULL, 0, NULL }, - { "tkf", roff_line_ignore, NULL, NULL, 0, NULL }, - { "tl", roff_unsupp, NULL, NULL, 0, NULL }, - { "tm", roff_line_ignore, NULL, NULL, 0, NULL }, - { "tm1", roff_line_ignore, NULL, NULL, 0, NULL }, - { "tmc", roff_line_ignore, NULL, NULL, 0, NULL }, - { "tr", roff_tr, NULL, NULL, 0, NULL }, - { "track", roff_line_ignore, NULL, NULL, 0, NULL }, - { "transchar", roff_line_ignore, NULL, NULL, 0, NULL }, - { "trf", roff_insec, NULL, NULL, 0, NULL }, - { "trimat", roff_line_ignore, NULL, NULL, 0, NULL }, - { "trin", roff_unsupp, NULL, NULL, 0, NULL }, - { "trnt", roff_unsupp, NULL, NULL, 0, NULL }, - { "troff", roff_line_ignore, NULL, NULL, 0, NULL }, - { "TS", roff_TS, NULL, NULL, 0, NULL }, - { "uf", roff_line_ignore, NULL, NULL, 0, NULL }, - { "ul", roff_line_ignore, NULL, NULL, 0, NULL }, - { "unformat", roff_unsupp, NULL, NULL, 0, NULL }, - { "unwatch", roff_line_ignore, NULL, NULL, 0, NULL }, - { "unwatchn", roff_line_ignore, NULL, NULL, 0, NULL }, - { "vpt", roff_line_ignore, NULL, NULL, 0, NULL }, - { "vs", roff_line_ignore, NULL, NULL, 0, NULL }, - { "warn", roff_line_ignore, NULL, NULL, 0, NULL }, - { "warnscale", roff_line_ignore, NULL, NULL, 0, NULL }, - { "watch", roff_line_ignore, NULL, NULL, 0, NULL }, - { "watchlength", roff_line_ignore, NULL, NULL, 0, NULL }, - { "watchn", roff_line_ignore, NULL, NULL, 0, NULL }, - { "wh", roff_unsupp, NULL, NULL, 0, NULL }, - { "while", roff_unsupp, NULL, NULL, 0, NULL }, - { "write", roff_insec, NULL, NULL, 0, NULL }, - { "writec", roff_insec, NULL, NULL, 0, NULL }, - { "writem", roff_insec, NULL, NULL, 0, NULL }, - { "xflag", roff_line_ignore, NULL, NULL, 0, NULL }, - { ".", roff_cblock, NULL, NULL, 0, NULL }, - { NULL, roff_userdef, NULL, NULL, 0, NULL }, + { roff_unsupp, NULL, NULL, 0 }, /* ab */ + { roff_line_ignore, NULL, NULL, 0 }, /* ad */ + { roff_line_ignore, NULL, NULL, 0 }, /* af */ + { roff_unsupp, NULL, NULL, 0 }, /* aln */ + { roff_unsupp, NULL, NULL, 0 }, /* als */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* am */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* am1 */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* ami */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* ami1 */ + { roff_ds, NULL, NULL, 0 }, /* as */ + { roff_ds, NULL, NULL, 0 }, /* as1 */ + { roff_unsupp, NULL, NULL, 0 }, /* asciify */ + { roff_line_ignore, NULL, NULL, 0 }, /* backtrace */ + { roff_line_ignore, NULL, NULL, 0 }, /* bd */ + { roff_line_ignore, NULL, NULL, 0 }, /* bleedat */ + { roff_unsupp, NULL, NULL, 0 }, /* blm */ + { roff_unsupp, NULL, NULL, 0 }, /* box */ + { roff_unsupp, NULL, NULL, 0 }, /* boxa */ + { roff_line_ignore, NULL, NULL, 0 }, /* bp */ + { roff_unsupp, NULL, NULL, 0 }, /* BP */ + { roff_unsupp, NULL, NULL, 0 }, /* break */ + { roff_line_ignore, NULL, NULL, 0 }, /* breakchar */ + { roff_line_ignore, NULL, NULL, 0 }, /* brnl */ + { roff_brp, NULL, NULL, 0 }, /* brp */ + { roff_line_ignore, NULL, NULL, 0 }, /* brpnl */ + { roff_unsupp, NULL, NULL, 0 }, /* c2 */ + { roff_cc, NULL, NULL, 0 }, /* cc */ + { roff_line_ignore, NULL, NULL, 0 }, /* ce */ + { roff_insec, NULL, NULL, 0 }, /* cf */ + { roff_line_ignore, NULL, NULL, 0 }, /* cflags */ + { roff_line_ignore, NULL, NULL, 0 }, /* ch */ + { roff_unsupp, NULL, NULL, 0 }, /* char */ + { roff_unsupp, NULL, NULL, 0 }, /* chop */ + { roff_line_ignore, NULL, NULL, 0 }, /* class */ + { roff_insec, NULL, NULL, 0 }, /* close */ + { roff_unsupp, NULL, NULL, 0 }, /* CL */ + { roff_line_ignore, NULL, NULL, 0 }, /* color */ + { roff_unsupp, NULL, NULL, 0 }, /* composite */ + { roff_unsupp, NULL, NULL, 0 }, /* continue */ + { roff_line_ignore, NULL, NULL, 0 }, /* cp */ + { roff_line_ignore, NULL, NULL, 0 }, /* cropat */ + { roff_line_ignore, NULL, NULL, 0 }, /* cs */ + { roff_line_ignore, NULL, NULL, 0 }, /* cu */ + { roff_unsupp, NULL, NULL, 0 }, /* da */ + { roff_unsupp, NULL, NULL, 0 }, /* dch */ + { roff_Dd, NULL, NULL, 0 }, /* Dd */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* de */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* de1 */ + { roff_line_ignore, NULL, NULL, 0 }, /* defcolor */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* dei */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* dei1 */ + { roff_unsupp, NULL, NULL, 0 }, /* device */ + { roff_unsupp, NULL, NULL, 0 }, /* devicem */ + { roff_unsupp, NULL, NULL, 0 }, /* di */ + { roff_unsupp, NULL, NULL, 0 }, /* do */ + { roff_ds, NULL, NULL, 0 }, /* ds */ + { roff_ds, NULL, NULL, 0 }, /* ds1 */ + { roff_unsupp, NULL, NULL, 0 }, /* dwh */ + { roff_unsupp, NULL, NULL, 0 }, /* dt */ + { roff_unsupp, NULL, NULL, 0 }, /* ec */ + { roff_unsupp, NULL, NULL, 0 }, /* ecr */ + { roff_unsupp, NULL, NULL, 0 }, /* ecs */ + { roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, /* el */ + { roff_unsupp, NULL, NULL, 0 }, /* em */ + { roff_EN, NULL, NULL, 0 }, /* EN */ + { roff_unsupp, NULL, NULL, 0 }, /* eo */ + { roff_unsupp, NULL, NULL, 0 }, /* EP */ + { roff_EQ, NULL, NULL, 0 }, /* EQ */ + { roff_line_ignore, NULL, NULL, 0 }, /* errprint */ + { roff_unsupp, NULL, NULL, 0 }, /* ev */ + { roff_unsupp, NULL, NULL, 0 }, /* evc */ + { roff_unsupp, NULL, NULL, 0 }, /* ex */ + { roff_line_ignore, NULL, NULL, 0 }, /* fallback */ + { roff_line_ignore, NULL, NULL, 0 }, /* fam */ + { roff_unsupp, NULL, NULL, 0 }, /* fc */ + { roff_unsupp, NULL, NULL, 0 }, /* fchar */ + { roff_line_ignore, NULL, NULL, 0 }, /* fcolor */ + { roff_line_ignore, NULL, NULL, 0 }, /* fdeferlig */ + { roff_line_ignore, NULL, NULL, 0 }, /* feature */ + { roff_line_ignore, NULL, NULL, 0 }, /* fkern */ + { roff_line_ignore, NULL, NULL, 0 }, /* fl */ + { roff_line_ignore, NULL, NULL, 0 }, /* flig */ + { roff_line_ignore, NULL, NULL, 0 }, /* fp */ + { roff_line_ignore, NULL, NULL, 0 }, /* fps */ + { roff_unsupp, NULL, NULL, 0 }, /* fschar */ + { roff_line_ignore, NULL, NULL, 0 }, /* fspacewidth */ + { roff_line_ignore, NULL, NULL, 0 }, /* fspecial */ + { roff_line_ignore, NULL, NULL, 0 }, /* ftr */ + { roff_line_ignore, NULL, NULL, 0 }, /* fzoom */ + { roff_line_ignore, NULL, NULL, 0 }, /* gcolor */ + { roff_line_ignore, NULL, NULL, 0 }, /* hc */ + { roff_line_ignore, NULL, NULL, 0 }, /* hcode */ + { roff_line_ignore, NULL, NULL, 0 }, /* hidechar */ + { roff_line_ignore, NULL, NULL, 0 }, /* hla */ + { roff_line_ignore, NULL, NULL, 0 }, /* hlm */ + { roff_line_ignore, NULL, NULL, 0 }, /* hpf */ + { roff_line_ignore, NULL, NULL, 0 }, /* hpfa */ + { roff_line_ignore, NULL, NULL, 0 }, /* hpfcode */ + { roff_line_ignore, NULL, NULL, 0 }, /* hw */ + { roff_line_ignore, NULL, NULL, 0 }, /* hy */ + { roff_line_ignore, NULL, NULL, 0 }, /* hylang */ + { roff_line_ignore, NULL, NULL, 0 }, /* hylen */ + { roff_line_ignore, NULL, NULL, 0 }, /* hym */ + { roff_line_ignore, NULL, NULL, 0 }, /* hypp */ + { roff_line_ignore, NULL, NULL, 0 }, /* hys */ + { roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, /* ie */ + { roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT }, /* if */ + { roff_block, roff_block_text, roff_block_sub, 0 }, /* ig */ + { roff_unsupp, NULL, NULL, 0 }, /* index */ + { roff_it, NULL, NULL, 0 }, /* it */ + { roff_unsupp, NULL, NULL, 0 }, /* itc */ + { roff_line_ignore, NULL, NULL, 0 }, /* IX */ + { roff_line_ignore, NULL, NULL, 0 }, /* kern */ + { roff_line_ignore, NULL, NULL, 0 }, /* kernafter */ + { roff_line_ignore, NULL, NULL, 0 }, /* kernbefore */ + { roff_line_ignore, NULL, NULL, 0 }, /* kernpair */ + { roff_unsupp, NULL, NULL, 0 }, /* lc */ + { roff_unsupp, NULL, NULL, 0 }, /* lc_ctype */ + { roff_unsupp, NULL, NULL, 0 }, /* lds */ + { roff_unsupp, NULL, NULL, 0 }, /* length */ + { roff_line_ignore, NULL, NULL, 0 }, /* letadj */ + { roff_insec, NULL, NULL, 0 }, /* lf */ + { roff_line_ignore, NULL, NULL, 0 }, /* lg */ + { roff_line_ignore, NULL, NULL, 0 }, /* lhang */ + { roff_unsupp, NULL, NULL, 0 }, /* linetabs */ + { roff_unsupp, NULL, NULL, 0 }, /* lnr */ + { roff_unsupp, NULL, NULL, 0 }, /* lnrf */ + { roff_unsupp, NULL, NULL, 0 }, /* lpfx */ + { roff_line_ignore, NULL, NULL, 0 }, /* ls */ + { roff_unsupp, NULL, NULL, 0 }, /* lsm */ + { roff_line_ignore, NULL, NULL, 0 }, /* lt */ + { roff_line_ignore, NULL, NULL, 0 }, /* mc */ + { roff_line_ignore, NULL, NULL, 0 }, /* mediasize */ + { roff_line_ignore, NULL, NULL, 0 }, /* minss */ + { roff_line_ignore, NULL, NULL, 0 }, /* mk */ + { roff_insec, NULL, NULL, 0 }, /* mso */ + { roff_line_ignore, NULL, NULL, 0 }, /* na */ + { roff_line_ignore, NULL, NULL, 0 }, /* ne */ + { roff_line_ignore, NULL, NULL, 0 }, /* nh */ + { roff_line_ignore, NULL, NULL, 0 }, /* nhychar */ + { roff_unsupp, NULL, NULL, 0 }, /* nm */ + { roff_unsupp, NULL, NULL, 0 }, /* nn */ + { roff_unsupp, NULL, NULL, 0 }, /* nop */ + { roff_nr, NULL, NULL, 0 }, /* nr */ + { roff_unsupp, NULL, NULL, 0 }, /* nrf */ + { roff_line_ignore, NULL, NULL, 0 }, /* nroff */ + { roff_line_ignore, NULL, NULL, 0 }, /* ns */ + { roff_insec, NULL, NULL, 0 }, /* nx */ + { roff_insec, NULL, NULL, 0 }, /* open */ + { roff_insec, NULL, NULL, 0 }, /* opena */ + { roff_line_ignore, NULL, NULL, 0 }, /* os */ + { roff_unsupp, NULL, NULL, 0 }, /* output */ + { roff_line_ignore, NULL, NULL, 0 }, /* padj */ + { roff_line_ignore, NULL, NULL, 0 }, /* papersize */ + { roff_line_ignore, NULL, NULL, 0 }, /* pc */ + { roff_line_ignore, NULL, NULL, 0 }, /* pev */ + { roff_insec, NULL, NULL, 0 }, /* pi */ + { roff_unsupp, NULL, NULL, 0 }, /* PI */ + { roff_line_ignore, NULL, NULL, 0 }, /* pl */ + { roff_line_ignore, NULL, NULL, 0 }, /* pm */ + { roff_line_ignore, NULL, NULL, 0 }, /* pn */ + { roff_line_ignore, NULL, NULL, 0 }, /* pnr */ + { roff_line_ignore, NULL, NULL, 0 }, /* po */ + { roff_line_ignore, NULL, NULL, 0 }, /* ps */ + { roff_unsupp, NULL, NULL, 0 }, /* psbb */ + { roff_unsupp, NULL, NULL, 0 }, /* pshape */ + { roff_insec, NULL, NULL, 0 }, /* pso */ + { roff_line_ignore, NULL, NULL, 0 }, /* ptr */ + { roff_line_ignore, NULL, NULL, 0 }, /* pvs */ + { roff_unsupp, NULL, NULL, 0 }, /* rchar */ + { roff_line_ignore, NULL, NULL, 0 }, /* rd */ + { roff_line_ignore, NULL, NULL, 0 }, /* recursionlimit */ + { roff_unsupp, NULL, NULL, 0 }, /* return */ + { roff_unsupp, NULL, NULL, 0 }, /* rfschar */ + { roff_line_ignore, NULL, NULL, 0 }, /* rhang */ + { roff_line_ignore, NULL, NULL, 0 }, /* rj */ + { roff_rm, NULL, NULL, 0 }, /* rm */ + { roff_unsupp, NULL, NULL, 0 }, /* rn */ + { roff_unsupp, NULL, NULL, 0 }, /* rnn */ + { roff_rr, NULL, NULL, 0 }, /* rr */ + { roff_line_ignore, NULL, NULL, 0 }, /* rs */ + { roff_line_ignore, NULL, NULL, 0 }, /* rt */ + { roff_unsupp, NULL, NULL, 0 }, /* schar */ + { roff_line_ignore, NULL, NULL, 0 }, /* sentchar */ + { roff_line_ignore, NULL, NULL, 0 }, /* shc */ + { roff_unsupp, NULL, NULL, 0 }, /* shift */ + { roff_line_ignore, NULL, NULL, 0 }, /* sizes */ + { roff_so, NULL, NULL, 0 }, /* so */ + { roff_line_ignore, NULL, NULL, 0 }, /* spacewidth */ + { roff_line_ignore, NULL, NULL, 0 }, /* special */ + { roff_line_ignore, NULL, NULL, 0 }, /* spreadwarn */ + { roff_line_ignore, NULL, NULL, 0 }, /* ss */ + { roff_line_ignore, NULL, NULL, 0 }, /* sty */ + { roff_unsupp, NULL, NULL, 0 }, /* substring */ + { roff_line_ignore, NULL, NULL, 0 }, /* sv */ + { roff_insec, NULL, NULL, 0 }, /* sy */ + { roff_T_, NULL, NULL, 0 }, /* T& */ + { roff_unsupp, NULL, NULL, 0 }, /* ta */ + { roff_unsupp, NULL, NULL, 0 }, /* tc */ + { roff_TE, NULL, NULL, 0 }, /* TE */ + { roff_TH, NULL, NULL, 0 }, /* TH */ + { roff_unsupp, NULL, NULL, 0 }, /* ti */ + { roff_line_ignore, NULL, NULL, 0 }, /* tkf */ + { roff_unsupp, NULL, NULL, 0 }, /* tl */ + { roff_line_ignore, NULL, NULL, 0 }, /* tm */ + { roff_line_ignore, NULL, NULL, 0 }, /* tm1 */ + { roff_line_ignore, NULL, NULL, 0 }, /* tmc */ + { roff_tr, NULL, NULL, 0 }, /* tr */ + { roff_line_ignore, NULL, NULL, 0 }, /* track */ + { roff_line_ignore, NULL, NULL, 0 }, /* transchar */ + { roff_insec, NULL, NULL, 0 }, /* trf */ + { roff_line_ignore, NULL, NULL, 0 }, /* trimat */ + { roff_unsupp, NULL, NULL, 0 }, /* trin */ + { roff_unsupp, NULL, NULL, 0 }, /* trnt */ + { roff_line_ignore, NULL, NULL, 0 }, /* troff */ + { roff_TS, NULL, NULL, 0 }, /* TS */ + { roff_line_ignore, NULL, NULL, 0 }, /* uf */ + { roff_line_ignore, NULL, NULL, 0 }, /* ul */ + { roff_unsupp, NULL, NULL, 0 }, /* unformat */ + { roff_line_ignore, NULL, NULL, 0 }, /* unwatch */ + { roff_line_ignore, NULL, NULL, 0 }, /* unwatchn */ + { roff_line_ignore, NULL, NULL, 0 }, /* vpt */ + { roff_line_ignore, NULL, NULL, 0 }, /* vs */ + { roff_line_ignore, NULL, NULL, 0 }, /* warn */ + { roff_line_ignore, NULL, NULL, 0 }, /* warnscale */ + { roff_line_ignore, NULL, NULL, 0 }, /* watch */ + { roff_line_ignore, NULL, NULL, 0 }, /* watchlength */ + { roff_line_ignore, NULL, NULL, 0 }, /* watchn */ + { roff_unsupp, NULL, NULL, 0 }, /* wh */ + { roff_unsupp, NULL, NULL, 0 }, /* while */ + { roff_insec, NULL, NULL, 0 }, /* write */ + { roff_insec, NULL, NULL, 0 }, /* writec */ + { roff_insec, NULL, NULL, 0 }, /* writem */ + { roff_line_ignore, NULL, NULL, 0 }, /* xflag */ + { roff_cblock, NULL, NULL, 0 }, /* . */ + { roff_userdef, NULL, NULL, 0 } }; /* not currently implemented: Ds em Eq LP Me PP pp Or Rd Sf SH */ @@ -591,65 +591,62 @@ static const struct predef predefs[PREDEFS_MAX] = { #include "predefs.in" }; -/* See roffhash_find() */ -#define ROFF_HASH(p) (p[0] - ASCII_LO) - static int roffit_lines; /* number of lines to delay */ static char *roffit_macro; /* nil-terminated macro line */ /* --- request table ------------------------------------------------------ */ -static void -roffhash_init(void) +struct ohash * +roffhash_alloc(enum roff_tok mintok, enum roff_tok maxtok) { - struct roffmac *n; - int buc, i; - - for (i = 0; i < (int)ROFF_USERDEF; i++) { - assert(roffs[i].name[0] >= ASCII_LO); - assert(roffs[i].name[0] <= ASCII_HI); + struct ohash *htab; + struct roffreq *req; + enum roff_tok tok; + size_t sz; + unsigned int slot; - buc = ROFF_HASH(roffs[i].name); + htab = mandoc_malloc(sizeof(*htab)); + mandoc_ohash_init(htab, 8, offsetof(struct roffreq, name)); - if (NULL != (n = hash[buc])) { - for ( ; n->next; n = n->next) - /* Do nothing. */ ; - n->next = &roffs[i]; - } else - hash[buc] = &roffs[i]; + for (tok = mintok; tok < maxtok; tok++) { + sz = strlen(roff_name[tok]); + req = mandoc_malloc(sizeof(*req) + sz + 1); + req->tok = tok; + memcpy(req->name, roff_name[tok], sz + 1); + slot = ohash_qlookup(htab, req->name); + ohash_insert(htab, slot, req); } + return htab; } -/* - * 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 roff_tok -roffhash_find(const char *p, size_t s) +void +roffhash_free(struct ohash *htab) { - int buc; - struct roffmac *n; - - /* - * libroff has an extremely simple hashtable, for the time - * being, which simply keys on the first character, which must - * be printable, then walks a chain. It works well enough until - * optimised. - */ + struct roffreq *req; + unsigned int slot; - if (p[0] < ASCII_LO || p[0] > ASCII_HI) - return TOKEN_NONE; - - buc = ROFF_HASH(p); + if (htab == NULL) + return; + for (req = ohash_first(htab, &slot); req != NULL; + req = ohash_next(htab, &slot)) + free(req); + ohash_delete(htab); + free(htab); +} - if (NULL == (n = hash[buc])) - return TOKEN_NONE; - for ( ; n; n = n->next) - if (0 == strncmp(n->name, p, s) && '\0' == n->name[(int)s]) - return (enum roff_tok)(n - roffs); +enum roff_tok +roffhash_find(struct ohash *htab, const char *name, size_t sz) +{ + struct roffreq *req; + const char *end; - return TOKEN_NONE; + if (sz) { + end = name + sz; + req = ohash_find(htab, ohash_qlookupi(htab, name, &end)); + } else + req = ohash_find(htab, ohash_qlookup(htab, name)); + return req == NULL ? TOKEN_NONE : req->tok; } /* --- stack of request blocks -------------------------------------------- */ @@ -740,7 +737,6 @@ roff_free1(struct roff *r) void roff_reset(struct roff *r) { - roff_free1(r); r->format = r->options & (MPARSE_MDOC | MPARSE_MAN); r->control = 0; @@ -749,8 +745,8 @@ roff_reset(struct roff *r) void roff_free(struct roff *r) { - roff_free1(r); + roffhash_free(r->reqtab); free(r); } @@ -761,12 +757,10 @@ roff_alloc(struct mparse *parse, int options) r = mandoc_calloc(1, sizeof(struct roff)); r->parse = parse; + r->reqtab = roffhash_alloc(0, ROFF_USERDEF); r->options = options; r->format = options & (MPARSE_MDOC | MPARSE_MAN); r->rstackpos = -1; - - roffhash_init(); - return r; } @@ -1489,7 +1483,7 @@ roff_endparse(struct roff *r) if (r->last) mandoc_msg(MANDOCERR_BLK_NOEND, r->parse, r->last->line, r->last->col, - roffs[r->last->tok].name); + roff_name[r->last->tok]); if (r->eqn) { mandoc_msg(MANDOCERR_BLK_NOEND, r->parse, @@ -1525,7 +1519,7 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos) maclen = roff_getname(r, &cp, ln, ppos); t = (r->current_string = roff_getstrn(r, mac, maclen)) - ? ROFF_USERDEF : roffhash_find(mac, maclen); + ? ROFF_USERDEF : roffhash_find(r->reqtab, mac, maclen); if (t != TOKEN_NONE) *pos = cp - buf; @@ -1663,7 +1657,7 @@ roff_block(ROFF_ARGS) if (namesz == 0 && tok != ROFF_ig) { mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse, - ln, ppos, roffs[tok].name); + ln, ppos, roff_name[tok]); return ROFF_IGN; } @@ -1704,7 +1698,7 @@ roff_block(ROFF_ARGS) if (*cp != '\0') mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, - ln, pos, ".%s ... %s", roffs[tok].name, cp); + ln, pos, ".%s ... %s", roff_name[tok], cp); return ROFF_IGN; } @@ -2013,7 +2007,7 @@ roff_insec(ROFF_ARGS) { mandoc_msg(MANDOCERR_REQ_INSEC, r->parse, - ln, ppos, roffs[tok].name); + ln, ppos, roff_name[tok]); return ROFF_IGN; } @@ -2022,7 +2016,7 @@ roff_unsupp(ROFF_ARGS) { mandoc_msg(MANDOCERR_REQ_UNSUPP, r->parse, - ln, ppos, roffs[tok].name); + ln, ppos, roff_name[tok]); return ROFF_IGN; } @@ -2095,7 +2089,7 @@ roff_cond(ROFF_ARGS) if (buf->buf[pos] == '\0') mandoc_msg(MANDOCERR_COND_EMPTY, r->parse, - ln, ppos, roffs[tok].name); + ln, ppos, roff_name[tok]); r->last->endspan = 1; @@ -16,6 +16,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +struct ohash; struct mdoc_arg; union mdoc_data; @@ -538,6 +539,8 @@ struct roff_man { struct roff_meta meta; /* Document meta-data. */ struct mparse *parse; /* Parse pointer. */ struct roff *roff; /* Roff parser state data. */ + struct ohash *mdocmac; /* Mdoc macro lookup table. */ + struct ohash *manmac; /* Man macro lookup table. */ const char *defos; /* Default operating system. */ struct roff_node *first; /* The first node parsed. */ struct roff_node *last; /* The last node parsed. */ @@ -569,4 +572,8 @@ struct roff_man { extern const char *const *roff_name; + void deroff(char **, const struct roff_node *); +struct ohash *roffhash_alloc(enum roff_tok, enum roff_tok); +enum roff_tok roffhash_find(struct ohash *, const char *, size_t); +void roffhash_free(struct ohash *); |