summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dummy.c63
-rw-r--r--mdocml.11
-rw-r--r--private.h157
-rw-r--r--roff.c456
4 files changed, 519 insertions, 158 deletions
diff --git a/dummy.c b/dummy.c
index 1b21115f..c4a678f3 100644
--- a/dummy.c
+++ b/dummy.c
@@ -25,7 +25,7 @@
#include "libmdocml.h"
#include "private.h"
-#ifdef __Linux__
+#ifdef __linux__
#define strlcat strncat
#endif
@@ -34,31 +34,35 @@ static int md_dummy_blk_out(int);
static int md_dummy_text_in(int, int *, char **);
static int md_dummy_text_out(int);
-static void dbg_indent(void);
+static void dbg_prologue(const char *);
+static void dbg_epilogue(void);
static int dbg_lvl = 0;
+static char dbg_line[72];
struct md_dummy {
struct rofftree *tree;
};
-static const char *const toknames[ROFF_MAX] = ROFF_NAMES;
-
-
static void
-dbg_indent(void)
+dbg_prologue(const char *p)
{
- char buf[128];
- int i;
-
- *buf = 0;
- assert(dbg_lvl >= 0);
+ int i;
+ (void)snprintf(dbg_line, sizeof(dbg_line) - 1, "%6s", p);
+ (void)strlcat(dbg_line, ": ", sizeof(dbg_line) - 1);
/* LINTED */
for (i = 0; i < dbg_lvl; i++)
- (void)strlcat(buf, " ", sizeof(buf) - 1);
+ (void)strlcat(dbg_line, " ", sizeof(dbg_line) - 1);
+}
+
- (void)printf("%s", buf);
+static void
+dbg_epilogue(void)
+{
+
+ assert(0 != dbg_line[0]);
+ (void)printf("%s\n", dbg_line);
}
@@ -66,8 +70,10 @@ static int
md_dummy_blk_in(int tok)
{
- dbg_indent();
- (void)printf("%s\n", toknames[tok]);
+ dbg_prologue("blk");
+ (void)strlcat(dbg_line, toknames[tok], sizeof(dbg_line) - 1);
+ dbg_epilogue();
+
dbg_lvl++;
return(1);
}
@@ -77,10 +83,7 @@ static int
md_dummy_blk_out(int tok)
{
- assert(dbg_lvl > 0);
dbg_lvl--;
- dbg_indent();
- (void)printf("%s\n", toknames[tok]);
return(1);
}
@@ -90,8 +93,26 @@ static int
md_dummy_text_in(int tok, int *argcp, char **argvp)
{
- dbg_indent();
- (void)printf("%s\n", toknames[tok]);
+ dbg_prologue("text");
+ (void)strlcat(dbg_line, toknames[tok], sizeof(dbg_line) - 1);
+ (void)strlcat(dbg_line, " ", sizeof(dbg_line) - 1);
+ while (ROFF_ARGMAX != *argcp) {
+ (void)strlcat(dbg_line, "[", sizeof(dbg_line) - 1);
+ (void)strlcat(dbg_line, tokargnames[*argcp],
+ sizeof(dbg_line) - 1);
+ if (*argvp) {
+ (void)strlcat(dbg_line, " [",
+ sizeof(dbg_line) - 1);
+ (void)strlcat(dbg_line, *argvp,
+ sizeof(dbg_line) - 1);
+ (void)strlcat(dbg_line, "]",
+ sizeof(dbg_line) - 1);
+ }
+ (void)strlcat(dbg_line, "]", sizeof(dbg_line) - 1);
+ argcp++;
+ argvp++;
+ }
+ dbg_epilogue();
return(1);
}
@@ -100,8 +121,6 @@ static int
md_dummy_text_out(int tok)
{
- dbg_indent();
- (void)printf("%s\n", toknames[tok]);
return(1);
}
diff --git a/mdocml.1 b/mdocml.1
index dcbc2b75..9f40d977 100644
--- a/mdocml.1
+++ b/mdocml.1
@@ -7,6 +7,7 @@
.Dt mdocml 1
.Os
.\"
+.Op foo
.Sh NAME
.Nm mdocml
.Nd compile manpage source into mark-up language
diff --git a/private.h b/private.h
index 191da07f..192e74cb 100644
--- a/private.h
+++ b/private.h
@@ -19,20 +19,22 @@
#ifndef PRIVATE_H
#define PRIVATE_H
+/* Input buffer (input read into buffer, then filled when empty). */
struct md_rbuf {
- int fd;
- char *name;
- char *buf;
- size_t bufsz;
- size_t line;
+ int fd; /* Open descriptor. */
+ char *name; /* Name of file. */
+ char *buf; /* Buffer. */
+ size_t bufsz; /* Size of buffer. */
+ size_t line; /* Current line number. */
};
+/* Output buffer (output buffered until full, then flushed). */
struct md_mbuf {
- int fd;
- char *name;
- char *buf;
- size_t bufsz;
- size_t pos;
+ int fd; /* Open descriptor. */
+ char *name; /* Name of file. */
+ char *buf; /* Buffer. */
+ size_t bufsz; /* Size of buffer. */
+ size_t pos; /* Position in buffer. */
};
#define ROFF___ 0
@@ -49,29 +51,89 @@ struct md_mbuf {
#define ROFF_Bl 11
#define ROFF_El 12
#define ROFF_It 13
-#define ROFF_An 14
-#define ROFF_Li 15
-#define ROFF_MAX 16
-
-#define ROFF_NAMES \
- { \
- "\\\"", \
- "Dd", \
- "Dt", \
- "Os", \
- "Sh", \
- "Ss", \
- "Pp", \
- "D1", \
- "Dl", \
- "Bd", \
- "Ed", \
- "Bl", \
- "El", \
- "It", \
- "An", \
- "Li", \
- }
+#define ROFF_Ad 15
+#define ROFF_An 16
+#define ROFF_Ar 17
+#define ROFF_Cd 18
+#define ROFF_Cm 19
+#define ROFF_Dv 20
+#define ROFF_Er 21
+#define ROFF_Ev 22
+#define ROFF_Ex 23
+#define ROFF_Fa 24
+#define ROFF_Fd 25
+#define ROFF_Fl 26
+#define ROFF_Fn 27
+#define ROFF_Ft 28
+#define ROFF_Ic 29
+#define ROFF_In 30
+#define ROFF_Li 31
+#define ROFF_Nd 32
+#define ROFF_Nm 33
+#define ROFF_Op 34
+#define ROFF_Ot 35
+#define ROFF_Pa 36
+#define ROFF_Rv 37
+#define ROFF_St 38
+#define ROFF_Va 39
+#define ROFF_Vt 40
+#define ROFF_Xr 41
+#define ROFF__A 42
+#define ROFF__B 43
+#define ROFF__D 44
+#define ROFF__I 45
+#define ROFF__J 46
+#define ROFF__N 47
+#define ROFF__O 48
+#define ROFF__P 49
+#define ROFF__R 50
+#define ROFF__T 51
+#define ROFF__V 52
+#define ROFF_Ac 53
+#define ROFF_Ao 54
+#define ROFF_Aq 55
+#define ROFF_At 56
+#define ROFF_Bc 57
+#define ROFF_Bf 58
+#define ROFF_Bo 59
+#define ROFF_Bq 60
+#define ROFF_Bsx 61
+#define ROFF_Bx 62
+#define ROFF_Db 63
+#define ROFF_Dc 64
+#define ROFF_Do 65
+#define ROFF_Dq 66
+#define ROFF_Ec 67
+#define ROFF_Ef 68
+#define ROFF_Em 60
+#define ROFF_Eo 70
+#define ROFF_Fx 71
+#define ROFF_Ms 72
+#define ROFF_No 73
+#define ROFF_Ns 74
+#define ROFF_Nx 75
+#define ROFF_Ox 76
+#define ROFF_Pc 77
+#define ROFF_Pf 78
+#define ROFF_Po 79
+#define ROFF_Pq 80
+#define ROFF_Qc 81
+#define ROFF_Ql 82
+#define ROFF_Qo 83
+#define ROFF_Qq 84
+#define ROFF_Re 85
+#define ROFF_Rs 86
+#define ROFF_Sc 87
+#define ROFF_So 88
+#define ROFF_Sq 89
+#define ROFF_Sm 90
+#define ROFF_Sx 91
+#define ROFF_Sy 92
+#define ROFF_Tn 93
+#define ROFF_Ux 94
+#define ROFF_Xc 95
+#define ROFF_Xo 96
+#define ROFF_MAX 97
#define ROFF_Split 0
#define ROFF_Nosplit 1
@@ -91,29 +153,12 @@ struct md_mbuf {
#define ROFF_Ohang 15
#define ROFF_Inset 16
#define ROFF_Column 17
-#define ROFF_ARGMAX 18
-
-#define ROFF_ARGNAMES \
- { \
- "split", \
- "nosplit", \
- "ragged", \
- "unfilled", \
- "literal", \
- "file", \
- "offset", \
- "bullet", \
- "dash", \
- "hyphen", \
- "item", \
- "enum", \
- "tag", \
- "diag", \
- "hang", \
- "ohang", \
- "inset", \
- "column", \
- }
+#define ROFF_Width 18
+#define ROFF_Compact 19
+#define ROFF_ARGMAX 20
+
+extern const char *const *toknames;
+extern const char *const *tokargnames;
/* FIXME: have a md_roff with all necessary parameters. */
diff --git a/roff.c b/roff.c
index a6d19f48..90e5ebdf 100644
--- a/roff.c
+++ b/roff.c
@@ -29,75 +29,81 @@
#define ROFF_MAXARG 10
+/* Whether we're entering or leaving a roff scope. */
enum roffd {
ROFF_ENTER = 0,
ROFF_EXIT
};
-/* FIXME: prolog roffs can be text roffs, too. */
-
+/* The type of a macro (see mdoc(7) for more). */
enum rofftype {
ROFF_COMMENT,
ROFF_TEXT,
ROFF_LAYOUT
};
+/* Arguments passed to a macro callback. */
#define ROFFCALL_ARGS \
int tok, struct rofftree *tree, \
const char *argv[], enum roffd type
struct rofftree;
+/* Describes a roff token (like D1 or Sh). */
struct rofftok {
- int (*cb)(ROFFCALL_ARGS);
- enum rofftype type;
+ int (*cb)(ROFFCALL_ARGS); /* Callback. */
+ const int *args; /* Args (or NULL). */
+ enum rofftype type; /* Type of macro. */
+ int symm; /* FIXME */
int flags;
-#define ROFF_NESTED (1 << 0)
-#define ROFF_PARSED (1 << 1)
-#define ROFF_CALLABLE (1 << 2)
-#define ROFF_QUOTES (1 << 3)
+#define ROFF_NESTED (1 << 0) /* Nested-layout. */
+#define ROFF_PARSED (1 << 1) /* "Parsed". */
+#define ROFF_CALLABLE (1 << 2) /* "Callable". */
+#define ROFF_QUOTES (1 << 3) /* Quoted args. */
};
+/* An argument to a roff token (like -split or -enum). */
struct roffarg {
- int tok;
int flags;
-#define ROFF_VALUE (1 << 0)
+#define ROFF_VALUE (1 << 0) /* Has a value. */
};
+/* mdocml remembers only the current parse node and the chain leading to
+ * the document root (scopes).
+ */
struct roffnode {
- int tok;
- struct roffnode *parent;
- size_t line;
+ int tok; /* Token id. */
+ struct roffnode *parent; /* Parent (or NULL). */
+ size_t line; /* Parsed at line. */
};
+/* State of file parse. */
struct rofftree {
- struct roffnode *last;
- time_t date;
- char os[64];
- char title[64];
- char section[64];
- char volume[64];
+ struct roffnode *last; /* Last parsed node. */
+ time_t date; /* `Dd' results. */
+ char os[64]; /* `Os' results. */
+ char title[64]; /* `Dt' results. */
+ char section[64]; /* `Dt' results. */
+ char volume[64]; /* `Dt' results. */
int state;
-#define ROFF_PRELUDE (1 << 1)
-#define ROFF_PRELUDE_Os (1 << 2)
-#define ROFF_PRELUDE_Dt (1 << 3)
-#define ROFF_PRELUDE_Dd (1 << 4)
-#define ROFF_BODY (1 << 5)
-
- roffin roffin;
- roffblkin roffblkin;
- roffout roffout;
- roffblkout roffblkout;
-
- struct md_mbuf *mbuf; /* NULL if !flush. */
- const struct md_args *args;
- const struct md_rbuf *rbuf;
+#define ROFF_PRELUDE (1 << 1) /* In roff prelude. */
+ /* FIXME: if we had prev ptrs, this wouldn't be necessary. */
+#define ROFF_PRELUDE_Os (1 << 2) /* `Os' is parsed. */
+#define ROFF_PRELUDE_Dt (1 << 3) /* `Dt' is parsed. */
+#define ROFF_PRELUDE_Dd (1 << 4) /* `Dd' is parsed. */
+#define ROFF_BODY (1 << 5) /* In roff body. */
+ roffin roffin; /* Text-macro cb. */
+ roffblkin roffblkin; /* Block-macro cb. */
+ roffout roffout; /* Text-macro cb. */
+ roffblkout roffblkout; /* Block-macro cb. */
+ struct md_mbuf *mbuf; /* Output (or NULL). */
+ const struct md_args *args; /* Global args. */
+ const struct md_rbuf *rbuf; /* Input. */
};
static int roff_Dd(ROFFCALL_ARGS);
static int roff_Dt(ROFFCALL_ARGS);
static int roff_Os(ROFFCALL_ARGS);
-
static int roff_layout(ROFFCALL_ARGS);
static int roff_text(ROFFCALL_ARGS);
@@ -108,55 +114,300 @@ static int rofffindtok(const char *);
static int rofffindarg(const char *);
static int rofffindcallable(const char *);
static int roffargs(int, char *, char **);
+static int roffargok(int, int);
+static int roffnextopt(int, const char ***, char **);
static int roffparse(struct rofftree *, char *, size_t);
static int textparse(const struct rofftree *,
const char *, size_t);
+/* Arguments for `An' macro. */
+static const int roffarg_An[] = {
+ ROFF_Split, ROFF_Nosplit, ROFF_ARGMAX };
+/* Arguments for `Bd' macro. */
+static const int roffarg_Bd[] = {
+ ROFF_Ragged, ROFF_Unfilled, ROFF_Literal, ROFF_File,
+ ROFF_Offset, ROFF_ARGMAX };
+/* Arguments for `Bl' macro. */
+static const int roffarg_Bl[] = {
+ ROFF_Bullet, ROFF_Dash, ROFF_Hyphen, ROFF_Item, ROFF_Enum,
+ ROFF_Tag, ROFF_Diag, ROFF_Hang, ROFF_Ohang, ROFF_Inset,
+ ROFF_Column, ROFF_Offset, ROFF_ARGMAX };
+
+/* FIXME: a big list of fixes that must occur.
+ *
+ * (1) Distinction not between ROFF_TEXT and ROFF_LAYOUT, but instead
+ * ROFF_ATOM and ROFF_NODE, which designate line spacing. If
+ * ROFF_ATOM, we need not remember any state.
+ *
+ * (2) Have a maybe-NULL list of possible subsequent children for each
+ * node. Bl, e.g., can only have It children (roffparse).
+ *
+ * (3) Have a maybe-NULL list of possible parents for each node. It,
+ * e.g., can only have Bl as a parent (roffparse).
+ *
+ * (N.B. If (2) were complete, (3) wouldn't be necessary.)
+ *
+ * (4) Scope rules. If Pp exists, it closes the scope out from the
+ * previous Pp (if it exists). Same with Sh and Ss. If El exists,
+ * it closes out Bl and interim It.
+ *
+ * (5) Nesting. Sh cannot be any descendant of Sh. Bl, however, can be
+ * nested within an It.
+ *
+ * Once that's done, we're golden.
+ */
+/* Table of all known tokens. */
static const struct rofftok tokens[ROFF_MAX] = {
- { NULL, ROFF_COMMENT, 0 },
- { roff_Dd, ROFF_TEXT, 0 }, /* Dd */
- { roff_Dt, ROFF_TEXT, 0 }, /* Dt */
- { roff_Os, ROFF_TEXT, 0 }, /* Os */
- { roff_layout, ROFF_LAYOUT, ROFF_PARSED }, /* Sh */
- { roff_layout, ROFF_LAYOUT, ROFF_PARSED }, /* Ss XXX */
- { roff_layout, ROFF_LAYOUT, 0 }, /* Pp */
- { roff_layout, ROFF_LAYOUT, 0 }, /* D1 */
- { roff_layout, ROFF_LAYOUT, 0 }, /* Dl */
- { roff_layout, ROFF_LAYOUT, 0 }, /* Bd */
- { roff_layout, ROFF_LAYOUT, 0 }, /* Ed */
- { roff_layout, ROFF_LAYOUT, 0 }, /* Bl */
- { roff_layout, ROFF_LAYOUT, 0 }, /* El */
- { roff_layout, ROFF_LAYOUT, 0 }, /* It */
- { roff_text, ROFF_TEXT, ROFF_PARSED }, /* An */
- { roff_text, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Li */
+ { NULL, NULL, 0, ROFF_COMMENT, 0 }, /* \" */
+ { roff_Dd, NULL, 0, ROFF_TEXT, 0 }, /* Dd */
+ { roff_Dt, NULL, 0, ROFF_TEXT, 0 }, /* Dt */
+ { roff_Os, NULL, 0, ROFF_TEXT, 0 }, /* Os */
+ { roff_layout, NULL, ROFF_Sh, ROFF_LAYOUT, ROFF_PARSED }, /* Sh */
+ { roff_layout, NULL, ROFF_Ss, ROFF_LAYOUT, ROFF_PARSED }, /* Ss */
+ { roff_layout, NULL, ROFF_Pp, ROFF_LAYOUT, 0 }, /* Pp */
+ { roff_layout, NULL, 0, ROFF_TEXT, 0 }, /* D1 */
+ { roff_layout, NULL, 0, ROFF_TEXT, 0 }, /* Dl */
+ { roff_layout, roffarg_Bd, 0, ROFF_LAYOUT, 0 }, /* Bd */
+ { roff_layout, NULL, ROFF_Bd, ROFF_LAYOUT, 0 }, /* Ed */
+ { roff_layout, roffarg_Bl, 0, ROFF_LAYOUT, 0 }, /* Bl */
+ { roff_layout, NULL, ROFF_Bl, ROFF_LAYOUT, 0 }, /* El */
+ { roff_layout, NULL, ROFF_It, ROFF_LAYOUT, 0 }, /* It */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ad */
+ { roff_text, roffarg_An, 0, ROFF_TEXT, ROFF_PARSED }, /* An */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ar */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Cd */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Cm */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Dv */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Er */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ev */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ex */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fa */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Fd */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fl */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Fn */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ft */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ic */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* In */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Li */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Nd */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Nm */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Op */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ot */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pa */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Rv */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* St */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Va */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Vt */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xr */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* %A */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE}, /* %B */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* %D */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE}, /* %I */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE}, /* %J */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* %N */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* %O */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* %P */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* %R */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* %T */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* %V */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ac */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ao */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Aq */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* At */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bc */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Bf */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bo */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bq */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Bsx */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Bx */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Db */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Dc */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Do */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Dq */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ec */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Ef */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Em */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Eo */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Fx */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ms */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* No */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ns */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Nx */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ox */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pc */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Pf */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Po */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pq */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Qc */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ql */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Qo */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Qq */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Re */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Rs */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sc */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* So */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sq */
+ { roff_text, NULL, 0, ROFF_TEXT, 0 }, /* Sm */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sx */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ux */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */
+ { roff_text, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */
};
-/* FIXME: multiple owners? */
-
+/* Table of all known token arguments. */
static const struct roffarg tokenargs[ROFF_ARGMAX] = {
- { ROFF_An, 0 }, /* split */
- { ROFF_An, 0 }, /* nosplit */
- { ROFF_Bd, 0 }, /* ragged */
- { ROFF_Bd, 0 }, /* unfilled */
- { ROFF_Bd, 0 }, /* literal */
- { ROFF_Bd, ROFF_VALUE }, /* file */
- { ROFF_Bd, ROFF_VALUE }, /* offset */
- { ROFF_Bl, 0 }, /* bullet */
- { ROFF_Bl, 0 }, /* dash */
- { ROFF_Bl, 0 }, /* hyphen */
- { ROFF_Bl, 0 }, /* item */
- { ROFF_Bl, 0 }, /* enum */
- { ROFF_Bl, 0 }, /* tag */
- { ROFF_Bl, 0 }, /* diag */
- { ROFF_Bl, 0 }, /* hang */
- { ROFF_Bl, 0 }, /* ohang */
- { ROFF_Bl, 0 }, /* inset */
- { ROFF_Bl, 0 }, /* column */
+ { 0 }, /* split */
+ { 0 }, /* nosplit */
+ { 0 }, /* ragged */
+ { 0 }, /* unfilled */
+ { 0 }, /* literal */
+ { ROFF_VALUE }, /* file */
+ { ROFF_VALUE }, /* offset */
+ { 0 }, /* bullet */
+ { 0 }, /* dash */
+ { 0 }, /* hyphen */
+ { 0 }, /* item */
+ { 0 }, /* enum */
+ { 0 }, /* tag */
+ { 0 }, /* diag */
+ { 0 }, /* hang */
+ { 0 }, /* ohang */
+ { 0 }, /* inset */
+ { 0 }, /* column */
+ { 0 }, /* width */
+ { 0 }, /* compact */
};
-static const char *const toknames[ROFF_MAX] = ROFF_NAMES;
-static const char *const tokargnames[ROFF_ARGMAX] = ROFF_ARGNAMES;
+const char *const toknamesp[ROFF_MAX] =
+ {
+ "\\\"",
+ "Dd", /* Title macros. */
+ "Dt",
+ "Os",
+ "Sh", /* Layout macros */
+ "Ss",
+ "Pp",
+ "D1",
+ "Dl",
+ "Bd",
+ "Ed",
+ "Bl",
+ "El",
+ "It",
+ "Ad", /* Text macros. */
+ "An",
+ "Ar",
+ "Cd",
+ "Cm",
+ "Dr",
+ "Er",
+ "Ev",
+ "Ex",
+ "Fa",
+ "Fd",
+ "Fl",
+ "Fn",
+ "Ft",
+ "Ex",
+ "Ic",
+ "In",
+ "Li",
+ "Nd",
+ "Nm",
+ "Op",
+ "Ot",
+ "Pa",
+ "Rv",
+ "St",
+ "Va",
+ "Vt",
+ "Xr",
+ "\%A", /* General text macros. */
+ "\%B",
+ "\%D",
+ "\%I",
+ "\%J",
+ "\%N",
+ "\%O",
+ "\%P",
+ "\%R",
+ "\%T",
+ "\%V",
+ "Ac",
+ "Ao",
+ "Aq",
+ "At",
+ "Bc",
+ "Bf",
+ "Bo",
+ "Bq",
+ "Bsx",
+ "Bx",
+ "Db",
+ "Dc",
+ "Do",
+ "Dq",
+ "Ec",
+ "Ef",
+ "Em",
+ "Eo",
+ "Fx",
+ "Ms",
+ "No",
+ "Ns",
+ "Nx",
+ "Ox",
+ "Pc",
+ "Pf",
+ "Po",
+ "Pq",
+ "Qc",
+ "Ql",
+ "Qo",
+ "Qq",
+ "Re",
+ "Rs",
+ "Sc",
+ "So",
+ "Sq",
+ "Sm",
+ "Sx",
+ "Sy",
+ "Tn",
+ "Ux",
+ "Xc", /* FIXME: do not support! */
+ "Xo", /* FIXME: do not support! */
+ };
+
+const char *const tokargnamesp[ROFF_ARGMAX] =
+ {
+ "split",
+ "nosplit",
+ "ragged",
+ "unfilled",
+ "literal",
+ "file",
+ "offset",
+ "bullet",
+ "dash",
+ "hyphen",
+ "item",
+ "enum",
+ "tag",
+ "diag",
+ "hang",
+ "ohang",
+ "inset",
+ "column",
+ "width",
+ "compact",
+ };
+
+const char *const *toknames = toknamesp;
+const char *const *tokargnames = tokargnamesp;
int
@@ -304,6 +555,8 @@ roffparse(struct rofftree *tree, char *buf, size_t sz)
tree->rbuf->name,
tree->rbuf->line);
return(0);
+
+ /* FIXME: .Bsx is three letters! */
} else if (ROFF_MAX == (tok = rofffindtok(buf + 1))) {
warnx("%s: unknown line token `%c%c' (line %zu)",
tree->rbuf->name,
@@ -439,6 +692,22 @@ roffnode_new(int tokid, struct rofftree *tree)
}
+static int
+roffargok(int tokid, int argid)
+{
+ const int *c;
+
+ if (NULL == (c = tokens[tokid].args))
+ return(0);
+
+ for ( ; ROFF_ARGMAX != *c; c++)
+ if (argid == *c)
+ return(1);
+
+ return(0);
+}
+
+
static void
roffnode_free(int tokid, struct rofftree *tree)
{
@@ -549,7 +818,7 @@ roff_Os(ROFFCALL_ARGS)
/* ARGUSED */
static int
-roffnextopt(const char ***in, char **val)
+roffnextopt(int tok, const char ***in, char **val)
{
const char *arg, **argv;
int v;
@@ -562,8 +831,16 @@ roffnextopt(const char ***in, char **val)
return(-1);
if ('-' != *arg)
return(-1);
+
+ /* FIXME: should we let this slide... ? */
+
if (ROFF_ARGMAX == (v = rofffindarg(&arg[1])))
return(-1);
+
+ /* FIXME: should we let this slide... ? */
+
+ if ( ! roffargok(tok, v))
+ return(-1);
if ( ! (ROFF_VALUE & tokenargs[v].flags))
return(v);
@@ -584,7 +861,8 @@ roff_layout(ROFFCALL_ARGS)
if (ROFF_PRELUDE & tree->state) {
warnx("%s: macro `%s' called in prelude (line %zu)",
- tree->rbuf->name, toknames[tok],
+ tree->rbuf->name,
+ toknames[tok],
tree->rbuf->line);
return(0);
}
@@ -595,19 +873,31 @@ roff_layout(ROFFCALL_ARGS)
}
i = 0;
- while (-1 != (c = roffnextopt(&argv, &v))) {
+
+ while (-1 != (c = roffnextopt(tok, &argv, &v))) {
if (ROFF_ARGMAX == c) {
- warnx("%s: error parsing `%s' args (line %zu)",
+ warnx("%s: error parsing `%s' args (line %zu)",
tree->rbuf->name,
toknames[tok],
tree->rbuf->line);
return(0);
+ } else if ( ! roffargok(tok, c)) {
+ warnx("%s: arg `%s' not for `%s' (line %zu)",
+ tree->rbuf->name,
+ tokargnames[c],
+ toknames[tok],
+ tree->rbuf->line);
+ return(0);
}
argcp[i] = c;
argvp[i] = v;
+ i++;
argv++;
}
+ argcp[i] = ROFF_ARGMAX;
+ argvp[i] = NULL;
+
if (NULL == roffnode_new(tok, tree))
return(0);
@@ -649,25 +939,31 @@ roff_text(ROFFCALL_ARGS)
if (ROFF_PRELUDE & tree->state) {
warnx("%s: macro `%s' called in prelude (line %zu)",
- tree->rbuf->name, toknames[tok],
+ tree->rbuf->name,
+ toknames[tok],
tree->rbuf->line);
return(0);
}
i = 0;
- while (-1 != (c = roffnextopt(&argv, &v))) {
+
+ while (-1 != (c = roffnextopt(tok, &argv, &v))) {
if (ROFF_ARGMAX == c) {
- warnx("%s: error parsing `%s' args (line %zu)",
+ warnx("%s: error parsing `%s' args (line %zu)",
tree->rbuf->name,
toknames[tok],
tree->rbuf->line);
return(0);
- }
+ }
argcp[i] = c;
argvp[i] = v;
+ i++;
argv++;
}
+ argcp[i] = ROFF_ARGMAX;
+ argvp[i] = NULL;
+
if ( ! (*tree->roffin)(tok, argcp, argvp))
return(0);