-static struct roffnode *roffnode_new(int, struct rofftree *);
-static void roffnode_free(struct rofftree *);
-static int roff_warn(const struct rofftree *,
- const char *, char *, ...);
-static int roff_warnp(const struct rofftree *,
- const char *, int, enum rofferr);
-static int roff_err(const struct rofftree *,
- const char *, char *, ...);
-static int roff_errp(const struct rofftree *,
- const char *, int, enum rofferr);
-static int roffpurgepunct(struct rofftree *, char **);
-static int roffscan(int, const int *);
-static int rofffindtok(const char *);
-static int rofffindarg(const char *);
-static int rofffindcallable(const char *);
-static int roffispunct(const char *);
-static int roffchecksec(struct rofftree *,
- const char *, int);
-static int roffargs(const struct rofftree *,
- int, char *, char **);
-static int roffargok(int, int);
-static int roffnextopt(const struct rofftree *,
- int, char ***, char **);
-static int roffparseopts(struct rofftree *, int,
- char ***, int *, char **);
-static int roffcall(struct rofftree *, int, char **);
-static int roffexit(struct rofftree *, int);
-static int roffparse(struct rofftree *, char *);
-static int textparse(struct rofftree *, char *);
-static int roffdata(struct rofftree *, int, char *);
-static int roffspecial(struct rofftree *, int,
- const char *, const int *,
- const char **, size_t, char **);
-static int roffsetname(struct rofftree *, char **);
-
-#ifdef __linux__
-extern size_t strlcat(char *, const char *, size_t);
-extern size_t strlcpy(char *, const char *, size_t);
-extern int vsnprintf(char *, size_t,
- const char *, va_list);
-extern char *strptime(const char *, const char *,
- struct tm *);
-#endif
-
-int
-roff_free(struct rofftree *tree, int flush)
-{
- int error, t;
- struct roffnode *n;
-
- error = 0;
-
- if ( ! flush)
- goto end;
-
- error = 1;
-
- if (ROFF_PRELUDE & tree->state) {
- (void)roff_err(tree, NULL, "prelude never finished");
- goto end;
- } else if ( ! (ROFFSec_NAME & tree->asec)) {
- (void)roff_err(tree, NULL, "missing `NAME' section");
- goto end;
- } else if ( ! (ROFFSec_NMASK & tree->asec))
- (void)roff_warn(tree, NULL, "missing suggested `NAME', "
- "`SYNOPSIS', `DESCRIPTION' sections");
-
- for (n = tree->last; n; n = n->parent) {
- if (0 != tokens[n->tok].ctx)
- continue;
- (void)roff_err(tree, NULL, "closing explicit scope "
- "`%s'", toknames[n->tok]);
- goto end;
- }
-
- while (tree->last) {
- t = tree->last->tok;
- if ( ! roffexit(tree, t))
- goto end;
- }
-
- if ( ! (*tree->cb.rofftail)(tree->arg, &tree->tm,
- tree->os, tree->title,
- tree->section, tree->volume))
- goto end;
-
- error = 0;
-
-end:
-
- while (tree->last)
- roffnode_free(tree);
-
- free(tree);
-
- return(error ? 0 : 1);
-}
-
-
-struct rofftree *
-roff_alloc(const struct roffcb *cb, void *args)
-{
- struct rofftree *tree;
-
- assert(args);
- assert(cb);
-
- if (NULL == (tree = calloc(1, sizeof(struct rofftree))))
- err(1, "calloc");
-
- tree->state = ROFF_PRELUDE;
- tree->arg = args;
- tree->section = ROFF_MSEC_MAX;
-
- (void)memcpy(&tree->cb, cb, sizeof(struct roffcb));
-
- return(tree);
-}
-
-
-int
-roff_engine(struct rofftree *tree, char *buf)
-{
-
- tree->cur = buf;
- assert(buf);
-
- if (0 == *buf)
- return(roff_err(tree, buf, "blank line"));
- else if ('.' != *buf)
- return(textparse(tree, buf));
-
- return(roffparse(tree, buf));
-}
-
-
-static int
-textparse(struct rofftree *tree, char *buf)
-{
- char *bufp;
-
- /* TODO: literal parsing. */
-
- if ( ! (ROFF_BODY & tree->state))
- return(roff_err(tree, buf, "data not in body"));
-
- /* 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;
- }