version 1.33, 2008/12/02 13:20:24 |
version 1.39, 2008/12/04 19:31:57 |
|
|
/* 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__ |
static size_t strlcat(char *, const char *, size_t); |
extern size_t strlcat(char *, const char *, size_t); |
static size_t strlcpy(char *, const char *, size_t); |
extern size_t strlcpy(char *, const char *, size_t); |
extern int vsnprintf(char *, size_t, |
extern int vsnprintf(char *, size_t, |
const char *, va_list); |
const char *, va_list); |
extern char *strptime(const char *, const char *, |
extern char *strptime(const char *, const char *, |
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) |
|
{ |
|
|
|
if (0 == *buf) |
|
return(1); |
|
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 1147 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 1180 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 1249 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 1259 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 1227 roff_layout(ROFFCALL_ARGS) |
|
Line 1268 roff_layout(ROFFCALL_ARGS) |
|
return(0); |
return(0); |
} else if (ROFF_EXIT == type) { |
} else if (ROFF_EXIT == type) { |
roffnode_free(tree); |
roffnode_free(tree); |
|
if ( ! (*tree->cb.roffblkbodyout)(tree->arg, tok)) |
|
return(0); |
return((*tree->cb.roffblkout)(tree->arg, tok)); |
return((*tree->cb.roffblkout)(tree->arg, tok)); |
} |
} |
|
|
Line 1248 roff_layout(ROFFCALL_ARGS) |
|
Line 1291 roff_layout(ROFFCALL_ARGS) |
|
if ( ! (*tree->cb.roffblkin)(tree->arg, tok, argcp, argvp)) |
if ( ! (*tree->cb.roffblkin)(tree->arg, tok, argcp, argvp)) |
return(0); |
return(0); |
if (NULL == *argv) |
if (NULL == *argv) |
return(1); |
return((*tree->cb.roffblkbodyin) |
if ( ! (*tree->cb.roffin)(tree->arg, tok, argcp, argvp)) |
(tree->arg, tok, argcp, argvp)); |
|
|
|
if ( ! (*tree->cb.roffblkheadin)(tree->arg, tok, argcp, argvp)) |
return(0); |
return(0); |
|
|
/* |
/* |
Line 1259 roff_layout(ROFFCALL_ARGS) |
|
Line 1304 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)) |
return((*tree->cb.roffout)(tree->arg, tok)); |
return(0); |
|
return((*tree->cb.roffblkbodyin) |
|
(tree->arg, tok, argcp, argvp)); |
} |
} |
|
|
/* |
/* |
Line 1276 roff_layout(ROFFCALL_ARGS) |
|
Line 1323 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 1293 roff_layout(ROFFCALL_ARGS) |
|
Line 1338 roff_layout(ROFFCALL_ARGS) |
|
* macro. |
* macro. |
*/ |
*/ |
|
|
if (NULL == *argv) |
if (NULL == *argv) { |
return((*tree->cb.roffout)(tree->arg, tok)); |
if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) |
|
return(0); |
|
return((*tree->cb.roffblkbodyin) |
|
(tree->arg, tok, argcp, argvp)); |
|
} |
|
|
/* |
/* |
* Expensive. Scan to the end of line then work backwards until |
* Expensive. Scan to the end of line then work backwards until |
Line 1304 roff_layout(ROFFCALL_ARGS) |
|
Line 1353 roff_layout(ROFFCALL_ARGS) |
|
if ( ! roffpurgepunct(tree, argv)) |
if ( ! roffpurgepunct(tree, argv)) |
return(0); |
return(0); |
|
|
return((*tree->cb.roffout)(tree->arg, tok)); |
if ( ! (*tree->cb.roffblkheadout)(tree->arg, tok)) |
|
return(0); |
|
return((*tree->cb.roffblkbodyin) |
|
(tree->arg, tok, argcp, argvp)); |
} |
} |
|
|
|
|
Line 1312 roff_layout(ROFFCALL_ARGS) |
|
Line 1364 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 1333 roff_text(ROFFCALL_ARGS) |
|
Line 1385 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 1366 roff_text(ROFFCALL_ARGS) |
|
Line 1417 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 1378 roff_text(ROFFCALL_ARGS) |
|
Line 1428 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; |
} |
} |
Line 1445 roff_err(const struct rofftree *tree, const char *pos, |
|
Line 1495 roff_err(const struct rofftree *tree, const char *pos, |
|
ROFF_ERROR, tree->cur, pos, buf); |
ROFF_ERROR, tree->cur, pos, buf); |
} |
} |
|
|
|
|
#ifdef __linux |
|
/* $OpenBSD$ */ |
|
|
|
/* |
|
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> |
|
* |
|
* 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. |
|
*/ |
|
static size_t |
|
strlcat(char *dst, const char *src, size_t siz) |
|
{ |
|
char *d = dst; |
|
const char *s = src; |
|
size_t n = siz; |
|
size_t dlen; |
|
|
|
/* Find the end of dst and adjust bytes left but don't go past |
|
* end */ |
|
while (n-- != 0 && *d != '\0') |
|
d++; |
|
dlen = d - dst; |
|
n = siz - dlen; |
|
|
|
if (n == 0) |
|
return(dlen + strlen(s)); |
|
while (*s != '\0') { |
|
if (n != 1) { |
|
*d++ = *s; |
|
n--; |
|
} |
|
s++; |
|
} |
|
*d = '\0'; |
|
|
|
return(dlen + (s - src)); /* count does not include NUL */ |
|
} |
|
|
|
|
|
static size_t |
|
strlcpy(char *dst, const char *src, size_t siz) |
|
{ |
|
char *d = dst; |
|
const char *s = src; |
|
size_t n = siz; |
|
|
|
/* Copy as many bytes as will fit */ |
|
if (n != 0) { |
|
while (--n != 0) { |
|
if ((*d++ = *s++) == '\0') |
|
break; |
|
} |
|
} |
|
|
|
/* Not enough room in dst, add NUL and traverse rest of src */ |
|
if (n == 0) { |
|
if (siz != 0) |
|
*d = '\0'; /* NUL-terminate dst */ |
|
while (*s++) |
|
; |
|
} |
|
|
|
return(s - src - 1); /* count does not include NUL */ |
|
} |
|
#endif /*__linux__*/ |
|