version 1.5, 2008/11/23 23:35:25 |
version 1.6, 2008/11/24 08:50:33 |
|
|
#include "libmdocml.h" |
#include "libmdocml.h" |
#include "private.h" |
#include "private.h" |
|
|
|
#define ROFF_MAXARG 10 |
|
|
enum roffd { |
enum roffd { |
ROFF_ENTER = 0, |
ROFF_ENTER = 0, |
ROFF_EXIT |
ROFF_EXIT |
|
|
|
|
#define ROFFCALL_ARGS \ |
#define ROFFCALL_ARGS \ |
const struct md_args *arg, struct md_mbuf *out, \ |
const struct md_args *arg, struct md_mbuf *out, \ |
const struct md_rbuf *in, const char *buf, size_t sz, \ |
const struct md_rbuf *in, const char *argv[], \ |
size_t pos, enum roffd type, struct rofftree *tree |
enum roffd type, struct rofftree *tree |
|
|
struct rofftree; |
struct rofftree; |
|
|
|
|
#define ROFF_NESTED (1 << 0) |
#define ROFF_NESTED (1 << 0) |
#define ROFF_PARSED (1 << 1) |
#define ROFF_PARSED (1 << 1) |
#define ROFF_CALLABLE (1 << 2) |
#define ROFF_CALLABLE (1 << 2) |
|
#define ROFF_QUOTES (1 << 3) |
}; |
}; |
|
|
struct roffnode { |
struct roffnode { |
Line 84 struct rofftree { |
|
Line 87 struct rofftree { |
|
#define ROFF_Sh 4 |
#define ROFF_Sh 4 |
#define ROFF_An 5 |
#define ROFF_An 5 |
#define ROFF_Li 6 |
#define ROFF_Li 6 |
#define ROFF_Max 7 |
#define ROFF_MAX 7 |
|
|
static int roff_Dd(ROFFCALL_ARGS); |
static int roff_Dd(ROFFCALL_ARGS); |
static int roff_Dt(ROFFCALL_ARGS); |
static int roff_Dt(ROFFCALL_ARGS); |
Line 98 static struct roffnode *roffnode_new(int, size_t, |
|
Line 101 static struct roffnode *roffnode_new(int, size_t, |
|
static void roffnode_free(int, struct rofftree *); |
static void roffnode_free(int, struct rofftree *); |
|
|
static int rofffind(const char *); |
static int rofffind(const char *); |
|
static int roffargs(int, char *, char **); |
static int roffparse(const struct md_args *, |
static int roffparse(const struct md_args *, |
struct md_mbuf *, |
struct md_mbuf *, |
const struct md_rbuf *, |
const struct md_rbuf *, |
const char *, size_t, |
char *, size_t, struct rofftree *); |
struct rofftree *); |
|
static int textparse(struct md_mbuf *, |
static int textparse(struct md_mbuf *, |
const struct md_rbuf *, |
const struct md_rbuf *, |
const char *, size_t, |
const char *, size_t, |
Line 112 static void dbg_enter(const struct md_args *, int); |
|
Line 115 static void dbg_enter(const struct md_args *, int); |
|
static void dbg_leave(const struct md_args *, int); |
static void dbg_leave(const struct md_args *, int); |
|
|
|
|
static const struct rofftok tokens[ROFF_Max] = |
static const struct rofftok tokens[ROFF_MAX] = |
{ |
{ |
{ ROFF___, "\\\"", NULL, ROFF_COMMENT, 0 }, |
{ ROFF___, "\\\"", NULL, ROFF_COMMENT, 0 }, |
{ ROFF_Dd, "Dd", roff_Dd, ROFF_TITLE, 0 }, |
{ ROFF_Dd, "Dd", roff_Dd, ROFF_TITLE, 0 }, |
Line 140 md_exit_html4_strict(const struct md_args *args, struc |
|
Line 143 md_exit_html4_strict(const struct md_args *args, struc |
|
/* LINTED */ |
/* LINTED */ |
while (tree->last) |
while (tree->last) |
if ( ! (*tokens[tree->last->tok].cb)(args, out, in, |
if ( ! (*tokens[tree->last->tok].cb)(args, out, in, |
NULL, 0, 0, ROFF_EXIT, tree)) |
NULL, ROFF_EXIT, tree)) |
out = NULL; |
out = NULL; |
|
|
if (out && (ROFF_PRELUDE & tree->state)) { |
if (out && (ROFF_PRELUDE & tree->state)) { |
Line 181 md_init_html4_strict(const struct md_args *args, struc |
|
Line 184 md_init_html4_strict(const struct md_args *args, struc |
|
|
|
int |
int |
md_line_html4_strict(const struct md_args *args, struct md_mbuf *out, |
md_line_html4_strict(const struct md_args *args, struct md_mbuf *out, |
const struct md_rbuf *in, const char *buf, |
const struct md_rbuf *in, char *buf, |
size_t sz, void *data) |
size_t sz, void *data) |
{ |
{ |
struct rofftree *tree; |
struct rofftree *tree; |
Line 231 textparse(struct md_mbuf *out, const struct md_rbuf *i |
|
Line 234 textparse(struct md_mbuf *out, const struct md_rbuf *i |
|
|
|
|
|
static int |
static int |
|
roffargs(int tok, char *buf, char **argv) |
|
{ |
|
int i; |
|
|
|
(void)tok;/* FIXME: quotable strings? */ |
|
|
|
assert(tok >= 0 && tok < ROFF_MAX); |
|
assert('.' == *buf); |
|
|
|
/* LINTED */ |
|
for (i = 0; *buf && i < ROFF_MAXARG; i++) { |
|
argv[i] = buf++; |
|
while (*buf && ! isspace(*buf)) |
|
buf++; |
|
if (NULL == *buf) { |
|
continue; |
|
} |
|
*buf++ = 0; |
|
while (*buf && isspace(*buf)) |
|
buf++; |
|
} |
|
|
|
assert(i > 0); |
|
if (i < ROFF_MAXARG) |
|
argv[i] = NULL; |
|
|
|
return(ROFF_MAXARG > i); |
|
} |
|
|
|
|
|
static int |
roffparse(const struct md_args *args, struct md_mbuf *out, |
roffparse(const struct md_args *args, struct md_mbuf *out, |
const struct md_rbuf *in, const char *buf, |
const struct md_rbuf *in, char *buf, size_t sz, |
size_t sz, struct rofftree *tree) |
struct rofftree *tree) |
{ |
{ |
int tokid, t; |
int tok, t; |
size_t pos; |
|
struct roffnode *node; |
struct roffnode *node; |
|
char *argv[ROFF_MAXARG]; |
|
|
assert(args); |
|
assert(out); |
|
assert(in); |
|
assert(buf); |
|
assert(sz > 0); |
assert(sz > 0); |
assert(tree); |
|
|
|
/* |
/* |
* Extract the token identifier from the buffer. If there's no |
* Extract the token identifier from the buffer. If there's no |
Line 257 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 286 roffparse(const struct md_args *args, struct md_mbuf * |
|
warnx("%s: malformed line (line %zu)", |
warnx("%s: malformed line (line %zu)", |
in->name, in->line); |
in->name, in->line); |
return(0); |
return(0); |
} else if (ROFF_Max == (tokid = rofffind(buf + 1))) { |
} else if (ROFF_MAX == (tok = rofffind(buf + 1))) { |
warnx("%s: unknown line token `%c%c' (line %zu)", |
warnx("%s: unknown line token `%c%c' (line %zu)", |
in->name, *(buf + 1), |
in->name, *(buf + 1), |
*(buf + 2), in->line); |
*(buf + 2), in->line); |
return(0); |
return(0); |
} |
} else if (ROFF_COMMENT == tokens[tok].type) |
|
/* Ignore comment tokens. */ |
|
return(1); |
|
|
|
if ( ! roffargs(tok, buf, argv)) { |
|
warnx("%s: too many arguments to `%s' (line %zu)", |
|
in->name, tokens[tok].name, in->line); |
|
return(0); |
|
} |
|
|
/* Domain cross-contamination (and sanity) checks. */ |
/* Domain cross-contamination (and sanity) checks. */ |
|
|
switch (tokens[tokid].type) { |
switch (tokens[tok].type) { |
case (ROFF_TITLE): |
case (ROFF_TITLE): |
if (ROFF_PRELUDE & tree->state) { |
if (ROFF_PRELUDE & tree->state) { |
assert( ! (ROFF_BODY & tree->state)); |
assert( ! (ROFF_BODY & tree->state)); |
Line 274 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 311 roffparse(const struct md_args *args, struct md_mbuf * |
|
} |
} |
assert(ROFF_BODY & tree->state); |
assert(ROFF_BODY & tree->state); |
warnx("%s: prelude token `%s' in body (line %zu)", |
warnx("%s: prelude token `%s' in body (line %zu)", |
in->name, tokens[tokid].name, in->line); |
in->name, tokens[tok].name, in->line); |
return(0); |
return(0); |
case (ROFF_LAYOUT): |
case (ROFF_LAYOUT): |
/* FALLTHROUGH */ |
/* FALLTHROUGH */ |
Line 285 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 322 roffparse(const struct md_args *args, struct md_mbuf * |
|
} |
} |
assert(ROFF_PRELUDE & tree->state); |
assert(ROFF_PRELUDE & tree->state); |
warnx("%s: body token `%s' in prelude (line %zu)", |
warnx("%s: body token `%s' in prelude (line %zu)", |
in->name, tokens[tokid].name, in->line); |
in->name, tokens[tok].name, in->line); |
return(0); |
return(0); |
case (ROFF_COMMENT): |
case (ROFF_COMMENT): |
return(1); |
return(1); |
Line 297 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 334 roffparse(const struct md_args *args, struct md_mbuf * |
|
* Text-domain checks. |
* Text-domain checks. |
*/ |
*/ |
|
|
if (ROFF_TEXT == tokens[tokid].type && |
if (ROFF_TEXT == tokens[tok].type && |
! (ROFF_PARSED & tokens[tokid].flags)) { |
! (ROFF_PARSED & tokens[tok].flags)) { |
warnx("%s: text token `%s' not callable (line %zu)", |
warnx("%s: text token `%s' not callable (line %zu)", |
in->name, tokens[tokid].name, in->line); |
in->name, tokens[tok].name, in->line); |
return(0); |
return(0); |
} |
} |
|
|
Line 315 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 352 roffparse(const struct md_args *args, struct md_mbuf * |
|
*/ |
*/ |
|
|
node = NULL; |
node = NULL; |
pos = 3; |
|
|
|
if (ROFF_LAYOUT == tokens[tokid].type && |
if (ROFF_LAYOUT == tokens[tok].type && |
! (ROFF_NESTED & tokens[tokid].flags)) { |
! (ROFF_NESTED & tokens[tok].flags)) { |
for (node = tree->last; node; node = node->parent) { |
for (node = tree->last; node; node = node->parent) { |
if (node->tok == tokid) |
if (node->tok == tok) |
break; |
break; |
|
|
/* Don't break nested scope. */ |
/* Don't break nested scope. */ |
Line 329 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 365 roffparse(const struct md_args *args, struct md_mbuf * |
|
continue; |
continue; |
warnx("%s: scope of %s (line %zu) broken by " |
warnx("%s: scope of %s (line %zu) broken by " |
"%s (line %zu)", in->name, |
"%s (line %zu)", in->name, |
tokens[tokid].name, |
tokens[tok].name, |
node->line, |
node->line, |
tokens[node->tok].name, |
tokens[node->tok].name, |
in->line); |
in->line); |
Line 338 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 374 roffparse(const struct md_args *args, struct md_mbuf * |
|
} |
} |
|
|
if (node) { |
if (node) { |
assert(ROFF_LAYOUT == tokens[tokid].type); |
assert(ROFF_LAYOUT == tokens[tok].type); |
assert( ! (ROFF_NESTED & tokens[tokid].flags)); |
assert( ! (ROFF_NESTED & tokens[tok].flags)); |
assert(node->tok == tokid); |
assert(node->tok == tok); |
|
|
/* Clear up to last scoped token. */ |
/* Clear up to last scoped token. */ |
|
|
Line 349 roffparse(const struct md_args *args, struct md_mbuf * |
|
Line 385 roffparse(const struct md_args *args, struct md_mbuf * |
|
t = tree->last->tok; |
t = tree->last->tok; |
if ( ! (*tokens[tree->last->tok].cb) |
if ( ! (*tokens[tree->last->tok].cb) |
(args, out, in, NULL, |
(args, out, in, NULL, |
0, 0, ROFF_EXIT, tree)) |
ROFF_EXIT, tree)) |
return(0); |
return(0); |
} while (t != tokid); |
} while (t != tok); |
} |
} |
|
|
/* Proceed with actual token processing. */ |
/* Proceed with actual token processing. */ |
|
|
return((*tokens[tokid].cb)(args, out, in, buf, sz, |
return((*tokens[tok].cb)(args, out, in, (const char **)argv, |
pos, ROFF_ENTER, tree)); |
ROFF_ENTER, tree)); |
} |
} |
|
|
|
|
Line 370 rofffind(const char *name) |
|
Line 406 rofffind(const char *name) |
|
/* FIXME: use a table, this is slow but ok for now. */ |
/* FIXME: use a table, this is slow but ok for now. */ |
|
|
/* LINTED */ |
/* LINTED */ |
for (i = 0; i < ROFF_Max; i++) |
for (i = 0; i < ROFF_MAX; i++) |
/* LINTED */ |
/* LINTED */ |
if (0 == strncmp(name, tokens[i].name, 2)) |
if (0 == strncmp(name, tokens[i].name, 2)) |
return((int)i); |
return((int)i); |
|
|
return(ROFF_Max); |
return(ROFF_MAX); |
} |
} |
|
|
|
|
Line 423 dbg_enter(const struct md_args *args, int tokid) |
|
Line 459 dbg_enter(const struct md_args *args, int tokid) |
|
assert(args); |
assert(args); |
if ( ! (args->dbg & MD_DBG_TREE)) |
if ( ! (args->dbg & MD_DBG_TREE)) |
return; |
return; |
assert(tokid >= 0 && tokid <= ROFF_Max); |
assert(tokid >= 0 && tokid <= ROFF_MAX); |
|
|
buf[0] = 0; |
buf[0] = 0; |
|
|
Line 462 dbg_leave(const struct md_args *args, int tokid) |
|
Line 498 dbg_leave(const struct md_args *args, int tokid) |
|
if (ROFF_LAYOUT != tokens[tokid].type) |
if (ROFF_LAYOUT != tokens[tokid].type) |
return; |
return; |
|
|
assert(tokid >= 0 && tokid <= ROFF_Max); |
assert(tokid >= 0 && tokid <= ROFF_MAX); |
assert(dbg_lvl > 0); |
assert(dbg_lvl > 0); |
dbg_lvl--; |
dbg_lvl--; |
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static int |
static int |
roff_Dd(ROFFCALL_ARGS) |
roff_Dd(ROFFCALL_ARGS) |
{ |
{ |
Line 491 roff_Dd(ROFFCALL_ARGS) |
|
Line 528 roff_Dd(ROFFCALL_ARGS) |
|
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static int |
static int |
roff_Dt(ROFFCALL_ARGS) |
roff_Dt(ROFFCALL_ARGS) |
{ |
{ |
Line 514 roff_Dt(ROFFCALL_ARGS) |
|
Line 552 roff_Dt(ROFFCALL_ARGS) |
|
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static int |
static int |
roff_Os(ROFFCALL_ARGS) |
roff_Os(ROFFCALL_ARGS) |
{ |
{ |
Line 546 roff_Os(ROFFCALL_ARGS) |
|
Line 585 roff_Os(ROFFCALL_ARGS) |
|
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static int |
static int |
roff_Sh(ROFFCALL_ARGS) |
roff_Sh(ROFFCALL_ARGS) |
{ |
{ |
Line 567 roff_Sh(ROFFCALL_ARGS) |
|
Line 607 roff_Sh(ROFFCALL_ARGS) |
|
} |
} |
|
|
|
|
|
/* ARGSUSED */ |
static int |
static int |
roff_Li(ROFFCALL_ARGS) |
roff_Li(ROFFCALL_ARGS) |
{ |
{ |
Line 598 parse_args(void) |
|
Line 639 parse_args(void) |
|
#endif |
#endif |
|
|
|
|
|
/* ARGSUSED */ |
static int |
static int |
roff_An(ROFFCALL_ARGS) |
roff_An(ROFFCALL_ARGS) |
{ |
{ |