version 1.28, 2008/12/01 16:01:28 |
version 1.30, 2008/12/01 21:25:48 |
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
* PERFORMANCE OF THIS SOFTWARE. |
* PERFORMANCE OF THIS SOFTWARE. |
*/ |
*/ |
|
#include <sys/param.h> |
|
|
#include <assert.h> |
#include <assert.h> |
#include <ctype.h> |
#include <ctype.h> |
#include <err.h> |
#include <err.h> |
Line 90 struct rofftree { |
|
Line 92 struct rofftree { |
|
struct roffnode *last; /* Last parsed node. */ |
struct roffnode *last; /* Last parsed node. */ |
char *cur; |
char *cur; |
|
|
time_t date; /* `Dd' results. */ |
struct tm tm; /* `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. */ |
Line 166 static const int roffarg_St[] = { |
|
Line 168 static const int roffarg_St[] = { |
|
|
|
static const int roffchild_Bl[] = { ROFF_It, ROFF_El, ROFF_MAX }; |
static const int roffchild_Bl[] = { ROFF_It, ROFF_El, ROFF_MAX }; |
static const int roffchild_Fo[] = { ROFF_Fa, ROFF_Fc, ROFF_MAX }; |
static const int roffchild_Fo[] = { ROFF_Fa, ROFF_Fc, ROFF_MAX }; |
static const int roffchild_Oo[] = { ROFF_Op, ROFF_Oc, ROFF_MAX }; |
|
static const int roffchild_Rs[] = { ROFF_Re, ROFF__A, ROFF__B, |
static const int roffchild_Rs[] = { ROFF_Re, ROFF__A, ROFF__B, |
ROFF__D, ROFF__I, ROFF__J, ROFF__N, ROFF__O, ROFF__P, |
ROFF__D, ROFF__I, ROFF__J, ROFF__N, ROFF__O, ROFF__P, |
ROFF__R, ROFF__T, ROFF__V, ROFF_MAX }; |
ROFF__R, ROFF__T, ROFF__V, ROFF_MAX }; |
|
|
static const int roffparent_El[] = { ROFF_Bl, ROFF_It, ROFF_MAX }; |
static const int roffparent_El[] = { ROFF_Bl, ROFF_It, ROFF_MAX }; |
static const int roffparent_Fc[] = { ROFF_Fo, ROFF_Fa, ROFF_MAX }; |
static const int roffparent_Fc[] = { ROFF_Fo, ROFF_Fa, ROFF_MAX }; |
static const int roffparent_Oc[] = { ROFF_Oo, ROFF_Oc, ROFF_MAX }; |
static const int roffparent_Oc[] = { ROFF_Oo, ROFF_MAX }; |
static const int roffparent_It[] = { ROFF_Bl, ROFF_It, ROFF_MAX }; |
static const int roffparent_It[] = { ROFF_Bl, ROFF_It, ROFF_MAX }; |
static const int roffparent_Re[] = { ROFF_Rs, ROFF_MAX }; |
static const int roffparent_Re[] = { ROFF_Rs, ROFF_MAX }; |
|
|
Line 277 static const struct rofftok tokens[ROFF_MAX] = { |
|
Line 278 static const struct rofftok tokens[ROFF_MAX] = { |
|
{ 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, roffchild_Oo, 0, ROFF_LAYOUT, 0 }, /* Oo */ |
{ roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Oo */ |
{ roff_noop, NULL, roffparent_Oc, NULL, ROFF_Oo, ROFF_LAYOUT, 0 }, /* Oc */ |
{ roff_noop, 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_noop, NULL, NULL, NULL, ROFF_Bk, ROFF_LAYOUT, 0 }, /* Ek */ |
{ roff_noop, NULL, NULL, NULL, ROFF_Bk, ROFF_LAYOUT, 0 }, /* Ek */ |
Line 398 roff_free(struct rofftree *tree, int flush) |
|
Line 399 roff_free(struct rofftree *tree, int flush) |
|
goto end; |
goto end; |
} |
} |
|
|
|
if ( ! (*tree->cb.rofftail)(tree->arg)) |
|
goto end; |
|
|
error = 0; |
error = 0; |
|
|
end: |
end: |
Line 439 roff_engine(struct rofftree *tree, char *buf) |
|
Line 443 roff_engine(struct rofftree *tree, char *buf) |
|
assert(buf); |
assert(buf); |
|
|
if (0 == *buf) { |
if (0 == *buf) { |
roff_warn(tree, buf, "blank line"); |
roff_err(tree, buf, "blank line"); |
return(0); |
return(0); |
} else if ('.' != *buf) |
} else if ('.' != *buf) |
return(textparse(tree, buf)); |
return(textparse(tree, buf)); |
|
|
textparse(const struct rofftree *tree, char *buf) |
textparse(const struct rofftree *tree, char *buf) |
{ |
{ |
|
|
|
if ( ! (ROFF_BODY & tree->state)) { |
|
roff_err(tree, buf, "data not in body"); |
|
return(0); |
|
} |
return((*tree->cb.roffdata)(tree->arg, 1, buf)); |
return((*tree->cb.roffdata)(tree->arg, 1, buf)); |
} |
} |
|
|
Line 898 roffparseopts(struct rofftree *tree, int tok, |
|
Line 906 roffparseopts(struct rofftree *tree, int tok, |
|
static int |
static int |
roff_Dd(ROFFCALL_ARGS) |
roff_Dd(ROFFCALL_ARGS) |
{ |
{ |
|
time_t t; |
|
char *p, buf[32]; |
|
|
if (ROFF_BODY & tree->state) { |
if (ROFF_BODY & tree->state) { |
assert( ! (ROFF_PRELUDE & tree->state)); |
assert( ! (ROFF_PRELUDE & tree->state)); |
Line 916 roff_Dd(ROFFCALL_ARGS) |
|
Line 926 roff_Dd(ROFFCALL_ARGS) |
|
return(0); |
return(0); |
} |
} |
|
|
/* TODO: parse date. */ |
|
|
|
assert(NULL == tree->last); |
assert(NULL == tree->last); |
tree->state |= ROFF_PRELUDE_Dd; |
|
|
|
|
argv++; |
|
|
|
if (0 == strcmp(*argv, "$Mdocdate$")) { |
|
t = time(NULL); |
|
if (NULL == localtime_r(&t, &tree->tm)) |
|
err(1, "localtime_r"); |
|
tree->state |= ROFF_PRELUDE_Dd; |
|
return(1); |
|
} |
|
|
|
/* Build this from Mdocdate or raw date. */ |
|
|
|
buf[0] = 0; |
|
p = *argv; |
|
|
|
if (0 != strcmp(*argv, "$Mdocdate:")) { |
|
while (*argv) { |
|
if (strlcat(buf, *argv++, sizeof(buf)) |
|
< sizeof(buf)) |
|
continue; |
|
roff_err(tree, p, "bad `Dd' date"); |
|
return(0); |
|
} |
|
if (strptime(buf, "%b%d,%Y", &tree->tm)) { |
|
tree->state |= ROFF_PRELUDE_Dd; |
|
return(1); |
|
} |
|
roff_err(tree, *argv, "bad `Dd' date"); |
|
return(0); |
|
} |
|
|
|
argv++; |
|
while (*argv && **argv != '$') { |
|
if (strlcat(buf, *argv++, sizeof(buf)) |
|
>= sizeof(buf)) { |
|
roff_err(tree, p, "bad `Dd' Mdocdate"); |
|
return(0); |
|
} |
|
if (strlcat(buf, " ", sizeof(buf)) |
|
>= sizeof(buf)) { |
|
roff_err(tree, p, "bad `Dd' Mdocdate"); |
|
return(0); |
|
} |
|
} |
|
if (NULL == *argv) { |
|
roff_err(tree, p, "bad `Dd' Mdocdate"); |
|
return(0); |
|
} |
|
|
|
if (NULL == strptime(buf, "%b %d %Y", &tree->tm)) { |
|
roff_err(tree, *argv, "bad `Dd' Mdocdate"); |
|
return(0); |
|
} |
|
|
|
tree->state |= ROFF_PRELUDE_Dd; |
return(1); |
return(1); |
} |
} |
|
|
Line 947 roff_Dt(ROFFCALL_ARGS) |
|
Line 1009 roff_Dt(ROFFCALL_ARGS) |
|
return(0); |
return(0); |
} |
} |
|
|
/* TODO: parse date. */ |
argv++; |
|
if (NULL == *argv) { |
|
roff_err(tree, *argv, "`Dt' needs document title"); |
|
return(0); |
|
} else if (strlcpy(tree->title, *argv, sizeof(tree->title)) |
|
>= sizeof(tree->title)) { |
|
roff_err(tree, *argv, "`Dt' document title too long"); |
|
return(0); |
|
} |
|
|
|
argv++; |
|
if (NULL == *argv) { |
|
roff_err(tree, *argv, "`Dt' needs section"); |
|
return(0); |
|
} else if (strlcpy(tree->section, *argv, sizeof(tree->section)) |
|
>= sizeof(tree->section)) { |
|
roff_err(tree, *argv, "`Dt' section too long"); |
|
return(0); |
|
} |
|
|
|
argv++; |
|
if (NULL == *argv) { |
|
tree->volume[0] = 0; |
|
} else if (strlcpy(tree->volume, *argv, sizeof(tree->volume)) |
|
>= sizeof(tree->volume)) { |
|
roff_err(tree, *argv, "`Dt' volume too long"); |
|
return(0); |
|
} |
|
|
assert(NULL == tree->last); |
assert(NULL == tree->last); |
tree->state |= ROFF_PRELUDE_Dt; |
tree->state |= ROFF_PRELUDE_Dt; |
|
|
Line 960 roff_Dt(ROFFCALL_ARGS) |
|
Line 1049 roff_Dt(ROFFCALL_ARGS) |
|
static int |
static int |
roff_Os(ROFFCALL_ARGS) |
roff_Os(ROFFCALL_ARGS) |
{ |
{ |
|
char *p; |
|
|
if (ROFF_EXIT == type) { |
if (ROFF_BODY & tree->state) { |
return((*tree->cb.rofftail)(tree->arg)); |
|
} else if (ROFF_BODY & tree->state) { |
|
assert( ! (ROFF_PRELUDE & tree->state)); |
assert( ! (ROFF_PRELUDE & tree->state)); |
assert(ROFF_PRELUDE_Os & tree->state); |
assert(ROFF_PRELUDE_Os & tree->state); |
return(roff_text(tok, tree, argv, type)); |
return(roff_text(tok, tree, argv, type)); |
Line 976 roff_Os(ROFFCALL_ARGS) |
|
Line 1064 roff_Os(ROFFCALL_ARGS) |
|
return(0); |
return(0); |
} |
} |
|
|
/* TODO: extract OS. */ |
tree->os[0] = 0; |
|
|
|
p = *++argv; |
|
|
|
while (*argv) { |
|
if (strlcat(tree->os, *argv++, sizeof(tree->os)) |
|
< sizeof(tree->os)) |
|
continue; |
|
roff_err(tree, p, "`Os' value too long"); |
|
return(0); |
|
} |
|
|
|
if (0 == tree->os[0]) |
|
if (strlcpy(tree->os, "LOCAL", sizeof(tree->os)) |
|
>= sizeof(tree->os)) { |
|
roff_err(tree, p, "`Os' value too long"); |
|
return(0); |
|
} |
|
|
tree->state |= ROFF_PRELUDE_Os; |
tree->state |= ROFF_PRELUDE_Os; |
tree->state &= ~ROFF_PRELUDE; |
tree->state &= ~ROFF_PRELUDE; |
tree->state |= ROFF_BODY; |
tree->state |= ROFF_BODY; |
Line 1094 roff_layout(ROFFCALL_ARGS) |
|
Line 1199 roff_layout(ROFFCALL_ARGS) |
|
while (i >= 0 && roffispunct(argv[i])) |
while (i >= 0 && roffispunct(argv[i])) |
i--; |
i--; |
|
|
assert(0 != i); |
|
i++; |
i++; |
|
|
/* LINTED */ |
/* LINTED */ |
Line 1225 roff_text(ROFFCALL_ARGS) |
|
Line 1329 roff_text(ROFFCALL_ARGS) |
|
|
|
while (i >= 0 && roffispunct(argv[i])) |
while (i >= 0 && roffispunct(argv[i])) |
i--; |
i--; |
|
|
assert(0 != i); |
|
i++; |
i++; |
|
|
/* LINTED */ |
/* LINTED */ |