version 1.35, 2008/12/03 19:21:58 |
version 1.38, 2008/12/04 16:34:59 |
|
|
/* TODO: (warn) NAME section has particular order. */ |
/* TODO: (warn) NAME section has particular order. */ |
/* TODO: unify empty-content tags a la <br />. */ |
/* TODO: unify empty-content tags a la <br />. */ |
/* TODO: macros with a set number of arguments? */ |
/* TODO: macros with a set number of arguments? */ |
|
/* TODO: validate Dt macro arguments. */ |
|
|
#define ROFF_MAXARG 32 |
|
|
|
enum roffd { |
enum roffd { |
ROFF_ENTER = 0, |
ROFF_ENTER = 0, |
ROFF_EXIT |
ROFF_EXIT |
Line 132 static int roffparseopts(struct rofftree *, int, |
|
Line 131 static int roffparseopts(struct rofftree *, int, |
|
char ***, int *, char **); |
char ***, int *, char **); |
static int roffcall(struct rofftree *, int, char **); |
static int roffcall(struct rofftree *, int, char **); |
static int roffparse(struct rofftree *, char *); |
static int roffparse(struct rofftree *, char *); |
static int textparse(const struct rofftree *, char *); |
static int textparse(struct rofftree *, char *); |
|
static int roffdata(struct rofftree *, int, char *); |
|
|
#ifdef __linux__ |
#ifdef __linux__ |
extern size_t strlcat(char *, const char *, size_t); |
extern size_t strlcat(char *, const char *, size_t); |
Line 271 static const struct rofftok tokens[ROFF_MAX] = { |
|
Line 271 static const struct rofftok tokens[ROFF_MAX] = { |
|
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */ |
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Sy */ |
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */ |
{ roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Tn */ |
{ 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, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */ |
{ roff_layout, NULL, NULL, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */ |
{ roff_noop, NULL, roffparent_Fc, NULL, ROFF_Fo, ROFF_LAYOUT, 0 }, /* Fc */ |
{ roff_noop, NULL, roffparent_Fc, NULL, ROFF_Fo, ROFF_LAYOUT, 0 }, /* Fc */ |
{ roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Oo */ |
{ roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Oo */ |
Line 449 roff_engine(struct rofftree *tree, char *buf) |
|
Line 449 roff_engine(struct rofftree *tree, char *buf) |
|
|
|
|
|
static int |
static int |
textparse(const struct rofftree *tree, char *buf) |
textparse(struct rofftree *tree, char *buf) |
{ |
{ |
|
char *bufp; |
|
|
|
/* TODO: literal parsing. */ |
|
|
if ( ! (ROFF_BODY & tree->state)) { |
if ( ! (ROFF_BODY & tree->state)) { |
roff_err(tree, buf, "data not in body"); |
roff_err(tree, buf, "data not in body"); |
return(0); |
return(0); |
} |
} |
return((*tree->cb.roffdata)(tree->arg, 1, buf)); |
|
|
/* LINTED */ |
|
while (*buf) { |
|
while (*buf && isspace(*buf)) |
|
buf++; |
|
|
|
if (0 == *buf) |
|
break; |
|
|
|
bufp = buf++; |
|
|
|
while (*buf && ! isspace(*buf)) |
|
buf++; |
|
|
|
if (0 != *buf) { |
|
*buf++ = 0; |
|
if ( ! roffdata(tree, 1, bufp)) |
|
return(0); |
|
continue; |
|
} |
|
|
|
if ( ! roffdata(tree, 1, bufp)) |
|
return(0); |
|
break; |
|
} |
|
|
|
return(1); |
} |
} |
|
|
|
|
Line 473 roffargs(const struct rofftree *tree, |
|
Line 502 roffargs(const struct rofftree *tree, |
|
p = buf; |
p = buf; |
|
|
/* LINTED */ |
/* LINTED */ |
for (i = 0; *buf && i < ROFF_MAXARG; i++) { |
for (i = 0; *buf && i < ROFF_MAXLINEARG; i++) { |
if ('\"' == *buf) { |
if ('\"' == *buf) { |
argv[i] = ++buf; |
argv[i] = ++buf; |
while (*buf && '\"' != *buf) |
while (*buf && '\"' != *buf) |
Line 498 roffargs(const struct rofftree *tree, |
|
Line 527 roffargs(const struct rofftree *tree, |
|
} |
} |
|
|
assert(i > 0); |
assert(i > 0); |
if (ROFF_MAXARG == i && *buf) { |
if (ROFF_MAXLINEARG == i && *buf) { |
roff_err(tree, p, "too many arguments for `%s'", toknames |
roff_err(tree, p, "too many arguments for `%s'", toknames |
[tok]); |
[tok]); |
return(0); |
return(0); |
Line 529 roffparse(struct rofftree *tree, char *buf) |
|
Line 558 roffparse(struct rofftree *tree, char *buf) |
|
{ |
{ |
int tok, t; |
int tok, t; |
struct roffnode *n; |
struct roffnode *n; |
char *argv[ROFF_MAXARG]; |
char *argv[ROFF_MAXLINEARG]; |
char **argvp; |
char **argvp; |
|
|
if (0 != *buf && 0 != *(buf + 1) && 0 != *(buf + 2)) |
if (0 != *buf && 0 != *(buf + 1) && 0 != *(buf + 2)) |
Line 906 roffpurgepunct(struct rofftree *tree, char **argv) |
|
Line 935 roffpurgepunct(struct rofftree *tree, char **argv) |
|
|
|
/* LINTED */ |
/* LINTED */ |
while (argv[i]) |
while (argv[i]) |
if ( ! (*tree->cb.roffdata)(tree->arg, 0, argv[i++])) |
if ( ! roffdata(tree, 0, argv[i++])) |
return(0); |
return(0); |
return(1); |
return(1); |
} |
} |
Line 937 roffparseopts(struct rofftree *tree, int tok, |
|
Line 966 roffparseopts(struct rofftree *tree, int tok, |
|
} |
} |
|
|
|
|
|
static int |
|
roffdata(struct rofftree *tree, int space, char *buf) |
|
{ |
|
int tok; |
|
|
|
if (0 == *buf) |
|
return(1); |
|
|
|
if (-1 == (tok = rofftok_scan(buf))) { |
|
roff_err(tree, buf, "invalid character sequence"); |
|
return(0); |
|
} else if (ROFFTok_MAX != tok) { |
|
if (ROFFTok_Null == tok) { /* FIXME */ |
|
buf += 2; |
|
return(roffdata(tree, space, buf)); |
|
} |
|
return((*tree->cb.rofftoken) |
|
(tree->arg, space != 0, tok)); |
|
} |
|
|
|
return((*tree->cb.roffdata)(tree->arg, |
|
space != 0, tree->cur, buf)); |
|
} |
|
|
|
|
/* ARGSUSED */ |
/* ARGSUSED */ |
static int |
static int |
roff_Dd(ROFFCALL_ARGS) |
roff_Dd(ROFFCALL_ARGS) |
Line 1107 roff_Sm(ROFFCALL_ARGS) |
|
Line 1161 roff_Sm(ROFFCALL_ARGS) |
|
tok, argcp, argvp, morep)) |
tok, argcp, argvp, morep)) |
return(0); |
return(0); |
|
|
while (*argv) { |
while (*argv) |
if ((*tree->cb.roffdata)(tree->arg, 1, *argv++)) |
if ( ! roffdata(tree, 1, *argv++)) |
continue; |
return(0); |
return(0); |
|
} |
|
|
|
return(1); |
return(1); |
} |
} |
Line 1142 roff_Ns(ROFFCALL_ARGS) |
|
Line 1194 roff_Ns(ROFFCALL_ARGS) |
|
} |
} |
|
|
if ( ! roffispunct(*argv)) { |
if ( ! roffispunct(*argv)) { |
if ((*tree->cb.roffdata)(tree->arg, 1, *argv++)) |
if ( ! roffdata(tree, 1, *argv++)) |
continue; |
return(0); |
return(0); |
continue; |
} |
} |
|
|
for (j = 0; argv[j]; j++) |
for (j = 0; argv[j]; j++) |
if ( ! roffispunct(argv[j])) |
if ( ! roffispunct(argv[j])) |
break; |
break; |
|
|
if (argv[j]) { |
if (argv[j]) { |
if ((*tree->cb.roffdata)(tree->arg, 0, *argv++)) |
if ( ! roffdata(tree, 0, *argv++)) |
continue; |
return(0); |
return(0); |
continue; |
} |
} |
|
|
break; |
break; |
Line 1210 roff_Os(ROFFCALL_ARGS) |
|
Line 1263 roff_Os(ROFFCALL_ARGS) |
|
|
|
assert(NULL == tree->last); |
assert(NULL == tree->last); |
|
|
return((*tree->cb.roffhead)(tree->arg)); |
return((*tree->cb.roffhead)(tree->arg, &tree->tm, |
|
tree->os, tree->title, tree->section, |
|
tree->volume)); |
} |
} |
|
|
|
|
Line 1218 roff_Os(ROFFCALL_ARGS) |
|
Line 1273 roff_Os(ROFFCALL_ARGS) |
|
static int |
static int |
roff_layout(ROFFCALL_ARGS) |
roff_layout(ROFFCALL_ARGS) |
{ |
{ |
int i, c, argcp[ROFF_MAXARG]; |
int i, c, argcp[ROFF_MAXLINEARG]; |
char *argvp[ROFF_MAXARG]; |
char *argvp[ROFF_MAXLINEARG]; |
|
|
if (ROFF_PRELUDE & tree->state) { |
if (ROFF_PRELUDE & tree->state) { |
roff_err(tree, *argv, "bad `%s' in prelude", |
roff_err(tree, *argv, "bad `%s' in prelude", |
Line 1263 roff_layout(ROFFCALL_ARGS) |
|
Line 1318 roff_layout(ROFFCALL_ARGS) |
|
|
|
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
i = 0; |
i = 0; |
while (*argv) { |
while (*argv) |
if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++)) |
if ( ! roffdata(tree, i++, *argv++)) |
return(0); |
return(0); |
i = 1; |
|
} |
|
if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) |
if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) |
return(0); |
return(0); |
return((*tree->cb.roffblkbodyin) |
return((*tree->cb.roffblkbodyin) |
Line 1283 roff_layout(ROFFCALL_ARGS) |
|
Line 1337 roff_layout(ROFFCALL_ARGS) |
|
while (*argv) { |
while (*argv) { |
if (ROFF_MAX == (c = rofffindcallable(*argv))) { |
if (ROFF_MAX == (c = rofffindcallable(*argv))) { |
assert(tree->arg); |
assert(tree->arg); |
if ( ! (*tree->cb.roffdata) |
if ( ! roffdata(tree, i++, *argv++)) |
(tree->arg, i, *argv++)) |
|
return(0); |
return(0); |
i = 1; |
|
continue; |
continue; |
} |
} |
if ( ! roffcall(tree, c, argv)) |
if ( ! roffcall(tree, c, argv)) |
Line 1326 roff_layout(ROFFCALL_ARGS) |
|
Line 1378 roff_layout(ROFFCALL_ARGS) |
|
static int |
static int |
roff_text(ROFFCALL_ARGS) |
roff_text(ROFFCALL_ARGS) |
{ |
{ |
int i, j, first, c, argcp[ROFF_MAXARG]; |
int i, j, first, c, argcp[ROFF_MAXLINEARG]; |
char *argvp[ROFF_MAXARG]; |
char *argvp[ROFF_MAXLINEARG]; |
|
|
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", |
Line 1347 roff_text(ROFFCALL_ARGS) |
|
Line 1399 roff_text(ROFFCALL_ARGS) |
|
|
|
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
if ( ! (ROFF_PARSED & tokens[tok].flags)) { |
i = 0; |
i = 0; |
while (*argv) { |
while (*argv) |
if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++)) |
if ( ! roffdata(tree, i++, *argv++)) |
return(0); |
return(0); |
i = 1; |
|
} |
|
return((*tree->cb.roffout)(tree->arg, tok)); |
return((*tree->cb.roffout)(tree->arg, tok)); |
} |
} |
|
|
Line 1380 roff_text(ROFFCALL_ARGS) |
|
Line 1431 roff_text(ROFFCALL_ARGS) |
|
} |
} |
|
|
if ( ! roffispunct(*argv)) { |
if ( ! roffispunct(*argv)) { |
if ( ! (*tree->cb.roffdata)(tree->arg, i, *argv++)) |
if ( ! roffdata(tree, i++, *argv++)) |
return(0); |
return(0); |
i = 1; |
|
continue; |
continue; |
} |
} |
|
|
Line 1392 roff_text(ROFFCALL_ARGS) |
|
Line 1442 roff_text(ROFFCALL_ARGS) |
|
break; |
break; |
|
|
if (argv[j]) { |
if (argv[j]) { |
if ( ! (*tree->cb.roffdata)(tree->arg, 0, *argv++)) |
if ( ! roffdata(tree, 0, *argv++)) |
return(0); |
return(0); |
continue; |
continue; |
} |
} |