version 1.12, 2008/11/27 16:54:58 |
version 1.14, 2008/11/28 11:21:12 |
Line 85 struct roffnode { |
|
Line 85 struct roffnode { |
|
|
|
struct rofftree { |
struct rofftree { |
struct roffnode *last; /* Last parsed node. */ |
struct roffnode *last; /* Last parsed node. */ |
time_t date; /* `Dd' results. */ |
|
char *cur; |
char *cur; |
|
|
|
time_t date; /* `Dd' results. */ |
char os[64]; /* `Os' results. */ |
char os[64]; /* `Os' results. */ |
char title[64]; /* `Dt' results. */ |
char title[64]; /* `Dt' results. */ |
char section[64]; /* `Dt' results. */ |
char section[64]; /* `Dt' results. */ |
char volume[64]; /* `Dt' results. */ |
char volume[64]; /* `Dt' results. */ |
|
|
int state; |
int state; |
#define ROFF_PRELUDE (1 << 1) /* In roff prelude. */ |
#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_Os (1 << 2) /* `Os' is parsed. */ |
#define ROFF_PRELUDE_Dt (1 << 3) /* `Dt' is parsed. */ |
#define ROFF_PRELUDE_Dt (1 << 3) /* `Dt' is parsed. */ |
#define ROFF_PRELUDE_Dd (1 << 4) /* `Dd' is parsed. */ |
#define ROFF_PRELUDE_Dd (1 << 4) /* `Dd' is parsed. */ |
#define ROFF_BODY (1 << 5) /* In roff body. */ |
#define ROFF_BODY (1 << 5) /* In roff body. */ |
|
|
struct md_mbuf *mbuf; /* Output (or NULL). */ |
struct md_mbuf *mbuf; /* Output (or NULL). */ |
const struct md_args *args; /* Global args. */ |
const struct md_args *args; /* Global args. */ |
const struct md_rbuf *rbuf; /* Input. */ |
const struct md_rbuf *rbuf; /* Input. */ |
Line 175 static const int roffparent_It[] = { ROFF_Bl, ROFF_It, |
|
Line 177 static const int roffparent_It[] = { ROFF_Bl, ROFF_It, |
|
static const int roffparent_Re[] = { ROFF_Rs, ROFF_MAX }; |
static const int roffparent_Re[] = { ROFF_Rs, ROFF_MAX }; |
|
|
/* Table of all known tokens. */ |
/* Table of all known tokens. */ |
static const struct rofftok tokens[ROFF_MAX] = |
static const struct rofftok tokens[ROFF_MAX] = { |
{ |
|
{roff_comment, NULL, NULL, NULL, 0, ROFF_COMMENT, 0 }, /* \" */ |
{roff_comment, NULL, NULL, NULL, 0, ROFF_COMMENT, 0 }, /* \" */ |
{ roff_Dd, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dd */ |
{ roff_Dd, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dd */ |
{ roff_Dt, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dt */ |
{ roff_Dt, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Dt */ |
Line 273 static const struct rofftok tokens[ROFF_MAX] = |
|
Line 274 static const struct rofftok tokens[ROFF_MAX] = |
|
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ux */ |
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ux */ |
{ NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */ |
{ NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xc */ |
{ NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */ |
{ NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */ |
{ roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Fo */ |
{ roff_layout, NULL, NULL, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */ |
{ roff_close, NULL, roffparent_Fc, NULL, ROFF_Fo, ROFF_LAYOUT, 0 }, /* Fc */ |
{ roff_close, NULL, roffparent_Fc, NULL, ROFF_Fo, ROFF_LAYOUT, 0 }, /* Fc */ |
{ roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Oo */ |
{ roff_layout, NULL, NULL, roffchild_Oo, 0, ROFF_LAYOUT, 0 }, /* Oo */ |
{ roff_close, NULL, roffparent_Oc, NULL, ROFF_Oo, ROFF_LAYOUT, 0 }, /* Oc */ |
{ roff_close, NULL, roffparent_Oc, NULL, ROFF_Oo, ROFF_LAYOUT, 0 }, /* Oc */ |
{ roff_layout, roffarg_Bk, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Bk */ |
{ roff_layout, roffarg_Bk, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Bk */ |
{ roff_close, NULL, NULL, NULL, ROFF_Bk, ROFF_LAYOUT, 0 }, /* Ek */ |
{ roff_close, NULL, NULL, NULL, ROFF_Bk, ROFF_LAYOUT, 0 }, /* Ek */ |
}; |
}; |
|
|
/* Table of all known token arguments. */ |
/* Table of all known token arguments. */ |
static const int tokenargs[ROFF_ARGMAX] = |
static const int tokenargs[ROFF_ARGMAX] = { |
{ |
|
0, 0, 0, 0, |
0, 0, 0, 0, |
0, ROFF_VALUE, ROFF_VALUE, 0, |
0, ROFF_VALUE, ROFF_VALUE, 0, |
0, 0, 0, 0, |
0, 0, 0, 0, |
Line 301 static const int tokenargs[ROFF_ARGMAX] = |
|
Line 301 static const int tokenargs[ROFF_ARGMAX] = |
|
0, 0, 0, 0, |
0, 0, 0, 0, |
}; |
}; |
|
|
const char *const toknamesp[ROFF_MAX] = |
const char *const toknamesp[ROFF_MAX] = { |
{ |
|
"\\\"", "Dd", "Dt", "Os", |
"\\\"", "Dd", "Dt", "Os", |
"Sh", "Ss", "Pp", "D1", |
"Sh", "Ss", "Pp", "D1", |
"Dl", "Bd", "Ed", "Bl", |
"Dl", "Bd", "Ed", "Bl", |
Line 331 const char *const toknamesp[ROFF_MAX] = |
|
Line 330 const char *const toknamesp[ROFF_MAX] = |
|
"Bk", "Ek", |
"Bk", "Ek", |
}; |
}; |
|
|
const char *const tokargnamesp[ROFF_ARGMAX] = |
const char *const tokargnamesp[ROFF_ARGMAX] = { |
{ |
|
"split", "nosplit", "ragged", |
"split", "nosplit", "ragged", |
"unfilled", "literal", "file", |
"unfilled", "literal", "file", |
"offset", "bullet", "dash", |
"offset", "bullet", "dash", |
Line 355 const char *const tokargnamesp[ROFF_ARGMAX] = |
|
Line 353 const char *const tokargnamesp[ROFF_ARGMAX] = |
|
"svid4", "filled", "words", |
"svid4", "filled", "words", |
}; |
}; |
|
|
|
|
const char *const *toknames = toknamesp; |
const char *const *toknames = toknamesp; |
const char *const *tokargnames = tokargnamesp; |
const char *const *tokargnames = tokargnamesp; |
|
|
Line 363 const char *const *tokargnames = tokargnamesp; |
|
Line 360 const char *const *tokargnames = tokargnamesp; |
|
int |
int |
roff_free(struct rofftree *tree, int flush) |
roff_free(struct rofftree *tree, int flush) |
{ |
{ |
int error; |
int error, tok; |
|
|
assert(tree->mbuf); |
assert(tree->mbuf); |
if ( ! flush) |
if ( ! flush) |
tree->mbuf = NULL; |
tree->mbuf = NULL; |
|
|
/* LINTED */ |
/* LINTED */ |
while (tree->last) |
while (tree->last) { |
|
if (tree->last->parent) { |
|
tok = tree->last->tok; |
|
if (tokens[tok].ctx == 0) { |
|
warnx("%s: closing out explicit scope " |
|
"of `%s' from line %zu", |
|
tree->rbuf->name, |
|
toknames[tok], |
|
tree->last->line); |
|
tree->mbuf = NULL; |
|
} |
|
} |
if ( ! (*tokens[tree->last->tok].cb) |
if ( ! (*tokens[tree->last->tok].cb) |
(tree->last->tok, tree, NULL, ROFF_EXIT)) |
(tree->last->tok, tree, NULL, ROFF_EXIT)) |
/* Disallow flushing. */ |
/* Disallow flushing. */ |
tree->mbuf = NULL; |
tree->mbuf = NULL; |
|
} |
|
|
error = tree->mbuf ? 0 : 1; |
error = tree->mbuf ? 0 : 1; |
|
|
if (tree->mbuf && (ROFF_PRELUDE & tree->state)) { |
if (tree->mbuf && (ROFF_PRELUDE & tree->state)) { |
/*roff_warn(tree, "prelude never finished");*/ |
warnx("%s: prelude never finished", |
|
tree->rbuf->name); |
error = 1; |
error = 1; |
} |
} |
|
|
|
|
roff_engine(struct rofftree *tree, char *buf, size_t sz) |
roff_engine(struct rofftree *tree, char *buf, size_t sz) |
{ |
{ |
|
|
tree->cur = buf; |
tree->cur = NULL; |
|
|
if (0 == sz) { |
if (0 == sz) { |
roff_warn(tree, buf, "blank line"); |
roff_warn(tree, buf, "blank line"); |
Line 451 roffargs(const struct rofftree *tree, |
|
Line 461 roffargs(const struct rofftree *tree, |
|
while (*buf && '\"' != *buf) |
while (*buf && '\"' != *buf) |
buf++; |
buf++; |
if (0 == *buf) { |
if (0 == *buf) { |
roff_err(tree, p, argv[i], "unclosed " |
roff_err(tree, argv[i], "unclosed " |
"quote in argument " |
"quote in argument " |
"list for `%s'", |
"list for `%s'", |
toknames[tok]); |
toknames[tok]); |
Line 471 roffargs(const struct rofftree *tree, |
|
Line 481 roffargs(const struct rofftree *tree, |
|
|
|
assert(i > 0); |
assert(i > 0); |
if (ROFF_MAXARG == i && *buf) { |
if (ROFF_MAXARG == i && *buf) { |
roff_err(tree, p, p, "too many arguments for `%s'", toknames |
roff_err(tree, p, "too many arguments for `%s'", toknames |
[tok]); |
[tok]); |
return(0); |
return(0); |
} |
} |
Line 540 roffparse(struct rofftree *tree, char *buf, size_t sz) |
|
Line 550 roffparse(struct rofftree *tree, char *buf, size_t sz) |
|
*/ |
*/ |
|
|
if ( ! roffscan(tree->last->tok, tokens[tok].parents)) { |
if ( ! roffscan(tree->last->tok, tokens[tok].parents)) { |
warnx("%s: invalid parent `%s' for `%s' (line %zu)", |
roff_err(tree, *argvp, "`%s' has invalid parent `%s' " |
tree->rbuf->name, |
"from line %zu", toknames[tok], |
toknames[tree->last->tok], |
toknames[tree->rbuf->line], |
toknames[tok], tree->rbuf->line); |
tree->rbuf->line); |
return(0); |
return(0); |
} |
} |
|
|
if ( ! roffscan(tok, tokens[tree->last->tok].children)) { |
if ( ! roffscan(tok, tokens[tree->last->tok].children)) { |
warnx("%s: invalid child `%s' for `%s' (line %zu)", |
roff_err(tree, *argvp, "`%s' is invalid child for " |
tree->rbuf->name, toknames[tok], |
"`%s' from line %zu", toknames[tok], |
toknames[tree->last->tok], |
toknames[tree->rbuf->line], |
tree->rbuf->line); |
tree->rbuf->line); |
return(0); |
return(0); |
} |
} |
Line 632 roffparse(struct rofftree *tree, char *buf, size_t sz) |
|
Line 642 roffparse(struct rofftree *tree, char *buf, size_t sz) |
|
assert(tree->last); |
assert(tree->last); |
assert(tok != tokens[tok].ctx && 0 != tokens[tok].ctx); |
assert(tok != tokens[tok].ctx && 0 != tokens[tok].ctx); |
|
|
|
/* LINTED */ |
do { |
do { |
t = tree->last->tok; |
t = tree->last->tok; |
if ( ! (*tokens[t].cb)(t, tree, NULL, ROFF_EXIT)) |
if ( ! (*tokens[t].cb)(t, tree, NULL, ROFF_EXIT)) |
Line 898 roff_layout(ROFFCALL_ARGS) |
|
Line 909 roff_layout(ROFFCALL_ARGS) |
|
|
|
if (ROFF_EXIT == type) { |
if (ROFF_EXIT == type) { |
roffnode_free(tok, tree); |
roffnode_free(tok, tree); |
return((*tree->cb->roffblkout)(tok)); |
return((*tree->cb->roffblkout)(tree->args, tok)); |
} |
} |
|
|
|
assert(tree->mbuf); |
|
|
i = 0; |
i = 0; |
argv++; |
argv++; |
|
|
Line 920 roff_layout(ROFFCALL_ARGS) |
|
Line 933 roff_layout(ROFFCALL_ARGS) |
|
if (NULL == roffnode_new(tok, tree)) |
if (NULL == roffnode_new(tok, tree)) |
return(0); |
return(0); |
|
|
if ( ! (*tree->cb->roffin)(tok, argcp, argvp)) |
if ( ! (*tree->cb->roffin)(tree->args, tok, argcp, argvp)) |
return(0); |
return(0); |
|
|
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
|
while (*argv) { |
|
if ( ! md_buf_putstring(tree->mbuf, *argv++)) |
|
return(0); |
|
if ( ! md_buf_putchar(tree->mbuf, ' ')) |
|
return(0); |
|
} |
|
|
/* TODO: print all tokens. */ |
if ( ! md_buf_putchar(tree->mbuf, '\n')) |
|
return(0); |
|
|
if ( ! ((*tree->cb->roffout)(tok))) |
if ( ! ((*tree->cb->roffout)(tree->args, tok))) |
return(0); |
return(0); |
return((*tree->cb->roffblkin)(tok)); |
return((*tree->cb->roffblkin)(tree->args, tok)); |
} |
} |
|
|
while (*argv) { |
while (*argv) { |
Line 940 roff_layout(ROFFCALL_ARGS) |
|
Line 960 roff_layout(ROFFCALL_ARGS) |
|
toknames[c]); |
toknames[c]); |
return(0); |
return(0); |
} |
} |
if ( ! (*tokens[c].cb)(c, tree, |
if ( ! (*tokens[c].cb)(c, tree, argv, ROFF_ENTER)) |
argv, ROFF_ENTER)) |
|
return(0); |
return(0); |
|
break; |
} |
} |
|
|
/* TODO: print token. */ |
if ( ! md_buf_putstring(tree->mbuf, *argv++)) |
|
return(0); |
argv++; |
if ( ! md_buf_putchar(tree->mbuf, ' ')) |
|
return(0); |
} |
} |
|
|
if ( ! ((*tree->cb->roffout)(tok))) |
if (NULL == *argv && ! md_buf_putchar(tree->mbuf, '\n')) |
return(0); |
return(0); |
|
|
return((*tree->cb->roffblkin)(tok)); |
if ( ! ((*tree->cb->roffout)(tree->args, tok))) |
|
return(0); |
|
return((*tree->cb->roffblkin)(tree->args, tok)); |
} |
} |
|
|
|
|
Line 964 roff_text(ROFFCALL_ARGS) |
|
Line 987 roff_text(ROFFCALL_ARGS) |
|
int i, c, argcp[ROFF_MAXARG]; |
int i, c, argcp[ROFF_MAXARG]; |
char *v, *argvp[ROFF_MAXARG]; |
char *v, *argvp[ROFF_MAXARG]; |
|
|
|
assert(tree->mbuf); |
|
|
if (ROFF_PRELUDE & tree->state) { |
if (ROFF_PRELUDE & tree->state) { |
roff_err(tree, *argv, "`%s' disallowed in prelude", |
roff_err(tree, *argv, "`%s' disallowed in prelude", |
toknames[tok]); |
toknames[tok]); |
Line 986 roff_text(ROFFCALL_ARGS) |
|
Line 1011 roff_text(ROFFCALL_ARGS) |
|
argcp[i] = ROFF_ARGMAX; |
argcp[i] = ROFF_ARGMAX; |
argvp[i] = NULL; |
argvp[i] = NULL; |
|
|
if ( ! (*tree->cb->roffin)(tok, argcp, argvp)) |
if ( ! (*tree->cb->roffin)(tree->args, tok, argcp, argvp)) |
return(0); |
return(0); |
|
|
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
|
while (*argv) { |
/* TODO: print all tokens. */ |
if ( ! md_buf_putstring(tree->mbuf, *argv++)) |
|
return(0); |
return((*tree->cb->roffout)(tok)); |
if ( ! md_buf_putchar(tree->mbuf, ' ')) |
|
return(0); |
|
} |
|
if ( ! md_buf_putchar(tree->mbuf, '\n')) |
|
return(0); |
|
return((*tree->cb->roffout)(tree->args, tok)); |
} |
} |
|
|
while (*argv) { |
while (*argv) { |
Line 1007 roff_text(ROFFCALL_ARGS) |
|
Line 1037 roff_text(ROFFCALL_ARGS) |
|
if ( ! (*tokens[c].cb)(c, tree, |
if ( ! (*tokens[c].cb)(c, tree, |
argv, ROFF_ENTER)) |
argv, ROFF_ENTER)) |
return(0); |
return(0); |
|
break; |
} |
} |
|
|
/* TODO: print token. */ |
if ( ! md_buf_putstring(tree->mbuf, *argv++)) |
|
return(0); |
argv++; |
if ( ! md_buf_putchar(tree->mbuf, ' ')) |
|
return(0); |
} |
} |
|
|
return((*tree->cb->roffout)(tok)); |
if (NULL == *argv && ! md_buf_putchar(tree->mbuf, '\n')) |
|
return(0); |
|
|
|
return((*tree->cb->roffout)(tree->args, tok)); |
} |
} |
|
|
|
|
|
|
roff_special(ROFFCALL_ARGS) |
roff_special(ROFFCALL_ARGS) |
{ |
{ |
|
|
return((*tree->cb->roffspecial)(tok)); |
return((*tree->cb->roffspecial)(tree->args, tok)); |
} |
} |
|
|
|
|