summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--Makefile.depend7
-rw-r--r--libman.h1
-rw-r--r--libmandoc.h2
-rw-r--r--libmdoc.h1
-rw-r--r--man.c27
-rw-r--r--man_hash.c101
-rw-r--r--mandoc_headers.329
-rw-r--r--mdoc.c25
-rw-r--r--mdoc_hash.c95
-rw-r--r--mdoc_macro.c2
-rw-r--r--mdoc_validate.c14
-rw-r--r--read.c17
-rw-r--r--roff.c600
-rw-r--r--roff.h7
15 files changed, 368 insertions, 564 deletions
diff --git a/Makefile b/Makefile
index 24b19362..95c976c2 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/libman.h b/libman.h
index 5f086d64..fd39d2f9 100644
--- a/libman.h
+++ b/libman.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 *);
diff --git a/libmdoc.h b/libmdoc.h
index dd591073..8f919dd6 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -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 *);
diff --git a/man.c b/man.c
index a5638c84..39a50431 100644
--- a/man.c
+++ b/man.c
@@ -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
diff --git a/mdoc.c b/mdoc.c
index f370ec9d..64404025 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -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);
diff --git a/read.c b/read.c
index 6ffc1d91..dfa10e56 100644
--- a/read.c
+++ b/read.c
@@ -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)
diff --git a/roff.c b/roff.c
index 7469eac9..9476cb93 100644
--- a/roff.c
+++ b/roff.c
@@ -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;
diff --git a/roff.h b/roff.h
index 0450dc10..f0d43e7f 100644
--- a/roff.h
+++ b/roff.h
@@ -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 *);