=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.58 retrieving revision 1.63 diff -u -p -r1.58 -r1.63 --- mandoc/roff.c 2008/12/10 10:43:57 1.58 +++ mandoc/roff.c 2008/12/10 16:03:12 1.63 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.58 2008/12/10 10:43:57 kristaps Exp $ */ +/* $Id: roff.c,v 1.63 2008/12/10 16:03:12 kristaps Exp $ */ /* * Copyright (c) 2008 Kristaps Dzonsons * @@ -38,7 +38,6 @@ /* TODO: (warn) some sections need specific elements. */ /* TODO: (warn) NAME section has particular order. */ /* TODO: macros with a set number of arguments? */ -/* TODO: validate Dt macro arguments. */ /* FIXME: Bl -diag supposed to ignore callable children. */ struct roffnode { @@ -59,7 +58,7 @@ enum rofferr { ERR_PR_OOO, /* Prelude macro bad order. */ ERR_PR_REP, /* Prelude macro repeated. */ ERR_NOT_PR, /* Not allowed in prelude. */ - WRN_SECORD, /* Sections out-of-order. */ + WRN_SECORD /* Sections out-of-order. */ }; struct rofftree { @@ -71,12 +70,6 @@ struct rofftree { char title[64]; /* `Dt' results. */ enum roffmsec section; enum roffvol volume; - int state; -#define ROFF_PRELUDE (1 << 1) /* In roff prelude. */ /* FIXME: put into asec. */ -#define ROFF_PRELUDE_Os (1 << 2) /* `Os' is parsed. */ -#define ROFF_PRELUDE_Dt (1 << 3) /* `Dt' is parsed. */ -#define ROFF_PRELUDE_Dd (1 << 4) /* `Dd' is parsed. */ -#define ROFF_BODY (1 << 5) /* In roff body. */ struct roffcb cb; /* Callbacks. */ void *arg; /* Callbacks' arg. */ int csec; /* Current section. */ @@ -100,7 +93,7 @@ static int rofffindarg(const char *); static int rofffindcallable(const char *); static int roffispunct(const char *); static int roffchecksec(struct rofftree *, - const char *, int); + const char *, int, int); static int roffargs(const struct rofftree *, int, char *, char **); static int roffargok(int, int); @@ -140,10 +133,7 @@ roff_free(struct rofftree *tree, int flush) error = 1; - if (ROFF_PRELUDE & tree->state) { - (void)roff_err(tree, NULL, "prelude never finished"); - goto end; - } else if ( ! (ROFFSec_NAME & tree->asec)) { + if ( ! (ROFFSec_NAME & tree->asec)) { (void)roff_err(tree, NULL, "missing `NAME' section"); goto end; } else if ( ! (ROFFSec_NMASK & tree->asec)) @@ -164,7 +154,9 @@ roff_free(struct rofftree *tree, int flush) goto end; } - if ( ! (*tree->cb.rofftail)(tree->arg)) + if ( ! (*tree->cb.rofftail)(tree->arg, &tree->tm, + tree->os, tree->title, + tree->section, tree->volume)) goto end; error = 0; @@ -191,7 +183,6 @@ roff_alloc(const struct roffcb *cb, void *args) if (NULL == (tree = calloc(1, sizeof(struct rofftree)))) err(1, "calloc"); - tree->state = ROFF_PRELUDE; tree->arg = args; tree->section = ROFF_MSEC_MAX; @@ -224,8 +215,8 @@ textparse(struct rofftree *tree, char *buf) /* TODO: literal parsing. */ - if ( ! (ROFF_BODY & tree->state)) - return(roff_err(tree, buf, "data not in body")); + if ( ! (ROFFSec_NAME & tree->asec)) + return(roff_err(tree, buf, "data before `NAME' section")); /* LINTED */ while (*buf) { @@ -352,13 +343,11 @@ roffparse(struct rofftree *tree, char *buf) * Prelude macros break some assumptions, so branch now. */ - if (ROFF_PRELUDE & tree->state) { + if ( ! (ROFFSec_PR_Dd & tree->asec)) { assert(NULL == tree->last); return(roffcall(tree, tok, argvp)); } - assert(ROFF_BODY & tree->state); - /* * First check that our possible parents and parent's possible * children are satisfied. @@ -525,76 +514,91 @@ rofffindtok(const char *buf) static int -roffchecksec(struct rofftree *tree, const char *start, int sec) +roffchecksec(struct rofftree *tree, + const char *start, int sec, int fail) { - int prior; switch (sec) { + case(ROFFSec_PR_Dd): + return(1); + case(ROFFSec_PR_Dt): + if (ROFFSec_PR_Dd & tree->asec) + return(1); + break; + case(ROFFSec_PR_Os): + if (ROFFSec_PR_Dt & tree->asec) + return(1); + break; + case(ROFFSec_NAME): + if (ROFFSec_PR_Os & tree->asec) + return(1); + break; case(ROFFSec_SYNOP): - if ((prior = ROFFSec_NAME) & tree->asec) + if (ROFFSec_NAME & tree->asec) return(1); break; case(ROFFSec_DESC): - if ((prior = ROFFSec_SYNOP) & tree->asec) + if (ROFFSec_SYNOP & tree->asec) return(1); break; case(ROFFSec_RETVAL): - if ((prior = ROFFSec_DESC) & tree->asec) + if (ROFFSec_DESC & tree->asec) return(1); break; case(ROFFSec_ENV): - if ((prior = ROFFSec_RETVAL) & tree->asec) + if (ROFFSec_RETVAL & tree->asec) return(1); break; case(ROFFSec_FILES): - if ((prior = ROFFSec_ENV) & tree->asec) + if (ROFFSec_ENV & tree->asec) return(1); break; case(ROFFSec_EX): - if ((prior = ROFFSec_FILES) & tree->asec) + if (ROFFSec_FILES & tree->asec) return(1); break; case(ROFFSec_DIAG): - if ((prior = ROFFSec_EX) & tree->asec) + if (ROFFSec_EX & tree->asec) return(1); break; case(ROFFSec_ERRS): - if ((prior = ROFFSec_DIAG) & tree->asec) + if (ROFFSec_DIAG & tree->asec) return(1); break; case(ROFFSec_SEEALSO): - if ((prior = ROFFSec_ERRS) & tree->asec) + if (ROFFSec_ERRS & tree->asec) return(1); break; case(ROFFSec_STAND): - if ((prior = ROFFSec_SEEALSO) & tree->asec) + if (ROFFSec_SEEALSO & tree->asec) return(1); break; case(ROFFSec_HIST): - if ((prior = ROFFSec_STAND) & tree->asec) + if (ROFFSec_STAND & tree->asec) return(1); break; case(ROFFSec_AUTH): - if ((prior = ROFFSec_HIST) & tree->asec) + if (ROFFSec_HIST & tree->asec) return(1); break; case(ROFFSec_CAVEATS): - if ((prior = ROFFSec_AUTH) & tree->asec) + if (ROFFSec_AUTH & tree->asec) return(1); break; case(ROFFSec_BUGS): - if ((prior = ROFFSec_CAVEATS) & tree->asec) + if (ROFFSec_CAVEATS & tree->asec) return(1); break; default: return(1); } + if (fail) + return(0); return(roff_warnp(tree, start, ROFF_Sh, WRN_SECORD)); } -/* FIXME: move this into literals.c (or similar). */ static int roffispunct(const char *p) { @@ -918,23 +922,16 @@ roff_Dd(ROFFCALL_ARGS) char *p, buf[32]; size_t sz; - if (ROFF_BODY & tree->state) { - assert( ! (ROFF_PRELUDE & tree->state)); - assert(ROFF_PRELUDE_Dd & tree->state); + if (ROFFSec_PR_Os & tree->asec) return(roff_text(tok, tree, argv, type)); - } - - assert(ROFF_PRELUDE & tree->state); - assert( ! (ROFF_BODY & tree->state)); - - if (ROFF_PRELUDE_Dd & tree->state) + if (ROFFSec_PR_Dd & tree->asec) return(roff_errp(tree, *argv, tok, ERR_PR_REP)); - if (ROFF_PRELUDE_Dt & tree->state) + if ( ! roffchecksec(tree, *argv, ROFFSec_PR_Dd, 1)) return(roff_errp(tree, *argv, tok, ERR_PR_OOO)); assert(NULL == tree->last); - argv++; + tree->asec |= (tree->csec = ROFFSec_PR_Dd); /* * This is a bit complex because there are many forms the date @@ -946,7 +943,6 @@ roff_Dd(ROFFCALL_ARGS) t = time(NULL); if (NULL == localtime_r(&t, &tree->tm)) err(1, "localtime_r"); - tree->state |= ROFF_PRELUDE_Dd; return(1); } @@ -960,10 +956,8 @@ roff_Dd(ROFFCALL_ARGS) continue; return(roff_errp(tree, p, tok, ERR_BADARG)); } - if (strptime(buf, "%b%d,%Y", &tree->tm)) { - tree->state |= ROFF_PRELUDE_Dd; + if (strptime(buf, "%b%d,%Y", &tree->tm)) return(1); - } return(roff_errp(tree, p, tok, ERR_BADARG)); } @@ -981,7 +975,6 @@ roff_Dd(ROFFCALL_ARGS) if (NULL == strptime(buf, "%b %d %Y", &tree->tm)) return(roff_errp(tree, p, tok, ERR_BADARG)); - tree->state |= ROFF_PRELUDE_Dd; return(1); } @@ -992,21 +985,15 @@ roff_Dt(ROFFCALL_ARGS) { size_t sz; - if (ROFF_BODY & tree->state) { - assert( ! (ROFF_PRELUDE & tree->state)); - assert(ROFF_PRELUDE_Dt & tree->state); + if (ROFFSec_PR_Os & tree->asec) return(roff_text(tok, tree, argv, type)); - } - - assert(ROFF_PRELUDE & tree->state); - assert( ! (ROFF_BODY & tree->state)); - - if ( ! (ROFF_PRELUDE_Dd & tree->state)) - return(roff_errp(tree, *argv, tok, ERR_PR_OOO)); - if (ROFF_PRELUDE_Dt & tree->state) + if (ROFFSec_PR_Dt & tree->asec) return(roff_errp(tree, *argv, tok, ERR_PR_REP)); + if ( ! roffchecksec(tree, *argv, ROFFSec_PR_Dt, 1)) + return(roff_errp(tree, *argv, tok, ERR_PR_OOO)); argv++; + tree->asec |= (tree->csec = ROFFSec_PR_Dt); sz = sizeof(tree->title); if (NULL == *argv) @@ -1064,7 +1051,6 @@ roff_Dt(ROFFCALL_ARGS) return(roff_errp(tree, *argv, tok, ERR_BADARG)); assert(NULL == tree->last); - tree->state |= ROFF_PRELUDE_Dt; return(1); } @@ -1143,22 +1129,17 @@ roff_Os(ROFFCALL_ARGS) char *p; size_t sz; - if (ROFF_BODY & tree->state) { - assert( ! (ROFF_PRELUDE & tree->state)); - assert(ROFF_PRELUDE_Os & tree->state); + if (ROFFSec_PR_Os & tree->asec) return(roff_text(tok, tree, argv, type)); - } - - assert(ROFF_PRELUDE & tree->state); - if ( ! (ROFF_PRELUDE_Dt & tree->state) || - ! (ROFF_PRELUDE_Dd & tree->state)) + if ( ! roffchecksec(tree, *argv, ROFFSec_PR_Os, 1)) return(roff_errp(tree, *argv, tok, ERR_PR_OOO)); - tree->os[0] = 0; - p = *++argv; sz = sizeof(tree->os); + tree->asec |= (tree->csec = ROFFSec_PR_Os); + tree->os[0] = 0; + while (*argv) if (strlcat(tree->os, *argv++, sz) >= sz) return(roff_errp(tree, p, tok, ERR_ARGLEN)); @@ -1167,10 +1148,6 @@ roff_Os(ROFFCALL_ARGS) if (strlcpy(tree->os, "LOCAL", sz) >= sz) return(roff_errp(tree, p, tok, ERR_ARGLEN)); - tree->state |= ROFF_PRELUDE_Os; - tree->state &= ~ROFF_PRELUDE; - tree->state |= ROFF_BODY; - assert(ROFF_MSEC_MAX != tree->section); assert(0 != tree->title[0]); assert(0 != tree->os[0]); @@ -1188,7 +1165,7 @@ static int roff_layout(ROFFCALL_ARGS) { int i, c, argcp[ROFF_MAXLINEARG]; - char *argvp[ROFF_MAXLINEARG]; + char *argvp[ROFF_MAXLINEARG], *p; /* * The roff_layout function is for multi-line macros. A layout @@ -1204,7 +1181,7 @@ roff_layout(ROFFCALL_ARGS) assert( ! (ROFF_CALLABLE & tokens[tok].flags)); - if (ROFF_PRELUDE & tree->state) + if ( ! (ROFFSec_PR_Os & tree->asec)) return(roff_errp(tree, *argv, tok, ERR_NOT_PR)); if (ROFF_EXIT == type) { @@ -1214,7 +1191,7 @@ roff_layout(ROFFCALL_ARGS) return((*tree->cb.roffblkout)(tree->arg, tok)); } - argv++; + p = *argv++; assert( ! (ROFF_CALLABLE & tokens[tok].flags)); if ( ! roffparseopts(tree, tok, &argv, argcp, argvp)) @@ -1267,10 +1244,14 @@ roff_layout(ROFFCALL_ARGS) if (0 == tree->asec && ! (ROFFSec_NAME & tree->csec)) return(roff_err(tree, *argv, "`NAME' section " "must be first")); - if ( ! roffchecksec(tree, *argv, tree->csec)) + if ( ! roffchecksec(tree, *argv, tree->csec, 0)) return(0); tree->asec |= tree->csec; + + if ( ! roffspecial(tree, tok, p, argcp, + (const char **)argvp, 0, argv)) + return(0); break; default: break; @@ -1368,7 +1349,7 @@ roff_ordered(ROFFCALL_ARGS) * .Xr arg1 arg2 punctuation */ - if (ROFF_PRELUDE & tree->state) + if ( ! (ROFFSec_PR_Os & tree->asec)) return(roff_errp(tree, *argv, tok, ERR_NOT_PR)); first = (*argv == tree->cur); @@ -1440,7 +1421,7 @@ roff_text(ROFFCALL_ARGS) * v W f ; */ - if (ROFF_PRELUDE & tree->state) + if ( ! (ROFFSec_PR_Os & tree->asec)) return(roff_errp(tree, *argv, tok, ERR_NOT_PR)); first = (*argv == tree->cur);