=================================================================== RCS file: /cvs/mandoc/roff.c,v retrieving revision 1.27 retrieving revision 1.29 diff -u -p -r1.27 -r1.29 --- mandoc/roff.c 2008/12/01 15:32:36 1.27 +++ mandoc/roff.c 2008/12/01 16:14:34 1.29 @@ -1,4 +1,4 @@ -/* $Id: roff.c,v 1.27 2008/12/01 15:32:36 kristaps Exp $ */ +/* $Id: roff.c,v 1.29 2008/12/01 16:14:34 kristaps Exp $ */ /* * Copyright (c) 2008 Kristaps Dzonsons * @@ -166,14 +166,13 @@ static const int roffarg_St[] = { 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_Oo[] = { ROFF_Op, ROFF_Oc, ROFF_MAX }; static const int roffchild_Rs[] = { ROFF_Re, ROFF__A, ROFF__B, ROFF__D, ROFF__I, ROFF__J, ROFF__N, ROFF__O, ROFF__P, ROFF__R, ROFF__T, ROFF__V, 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_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_Re[] = { ROFF_Rs, ROFF_MAX }; @@ -236,7 +235,7 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Aq */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* At */ /* XXX at most 2 args */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bc */ - { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Bf */ /* FIXME */ + { roff_layout, NULL, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Bf */ /* FIXME */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Bo */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Bq */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Bsx */ @@ -246,7 +245,7 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Do */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Dq */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ec */ - { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, 0 }, /* Ef */ /* FIXME */ + { roff_noop, NULL, NULL, NULL, ROFF_Bf, ROFF_LAYOUT, 0 }, /* Ef */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Em */ /* XXX needs arg */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Eo */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Fx */ @@ -257,7 +256,7 @@ static const struct rofftok tokens[ROFF_MAX] = { { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Ox */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Pc */ { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED }, /* Pf */ - { roff_text, NULL, NULL, NULL, 0, ROFF_LAYOUT, ROFF_PARSED | ROFF_CALLABLE }, /* Po */ + { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Po */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE | ROFF_LSCOPE }, /* Pq */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Qc */ { roff_text, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Ql */ @@ -277,7 +276,7 @@ static const struct rofftok tokens[ROFF_MAX] = { { NULL, NULL, NULL, NULL, 0, ROFF_TEXT, ROFF_PARSED | ROFF_CALLABLE }, /* Xo */ { roff_layout, NULL, NULL, roffchild_Fo, 0, ROFF_LAYOUT, 0 }, /* Fo */ { 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_layout, roffarg_Bk, NULL, NULL, 0, ROFF_LAYOUT, 0 }, /* Bk */ { roff_noop, NULL, NULL, NULL, ROFF_Bk, ROFF_LAYOUT, 0 }, /* Ek */ @@ -380,14 +379,14 @@ roff_free(struct rofftree *tree, int flush) error = 1; if (ROFF_PRELUDE & tree->state) { - roff_warn(tree, NULL, "prelude never finished"); + roff_err(tree, NULL, "prelude never finished"); goto end; } - for (n = tree->last; n->parent; n = n->parent) { + for (n = tree->last; n; n = n->parent) { if (0 != tokens[n->tok].ctx) continue; - roff_warn(tree, NULL, "closing explicit scope `%s'", + roff_err(tree, NULL, "closing explicit scope `%s'", toknames[n->tok]); goto end; } @@ -439,7 +438,7 @@ roff_engine(struct rofftree *tree, char *buf) assert(buf); if (0 == *buf) { - roff_warn(tree, buf, "blank line"); + roff_err(tree, buf, "blank line"); return(0); } else if ('.' != *buf) return(textparse(tree, buf)); @@ -554,8 +553,7 @@ roffparse(struct rofftree *tree, char *buf) if (ROFF_PRELUDE & tree->state) { assert(NULL == tree->last); return((*tokens[tok].cb)(tok, tree, argvp, ROFF_ENTER)); - } else - assert(tree->last); + } assert(ROFF_BODY & tree->state); @@ -564,14 +562,16 @@ roffparse(struct rofftree *tree, char *buf) * children are satisfied. */ - if ( ! roffscan(tree->last->tok, tokens[tok].parents)) { + if (tree->last && ! roffscan + (tree->last->tok, tokens[tok].parents)) { roff_err(tree, *argvp, "`%s' has invalid parent `%s'", toknames[tok], toknames[tree->last->tok]); return(0); } - if ( ! roffscan(tok, tokens[tree->last->tok].children)) { + if (tree->last && ! roffscan + (tok, tokens[tree->last->tok].children)) { roff_err(tree, *argvp, "`%s' is invalid child of `%s'", toknames[tok], toknames[tree->last->tok]); @@ -614,6 +614,11 @@ roffparse(struct rofftree *tree, char *buf) n = NULL; break; } + if (tokens[n->tok].ctx == n->tok) + continue; + roff_err(tree, *argv, "`%s' breaks `%s' scope", + toknames[tok], toknames[n->tok]); + return(0); } /* @@ -647,9 +652,26 @@ roffparse(struct rofftree *tree, char *buf) * In this, the `El' tag closes out the scope of `Bl'. */ - assert(tree->last); assert(tok != tokens[tok].ctx && 0 != tokens[tok].ctx); + for (n = tree->last; n; n = n->parent) + if (n->tok != tokens[tok].ctx) { + if (n->tok == tokens[n->tok].ctx) + continue; + roff_err(tree, *argv, "`%s' breaks `%s' scope", + toknames[tok], toknames[n->tok]); + return(0); + } else + break; + + + if (NULL == n) { + roff_err(tree, *argv, "`%s' has no starting tag `%s'", + toknames[tok], + toknames[tokens[tok].ctx]); + return(0); + } + /* LINTED */ do { t = tree->last->tok; @@ -657,7 +679,6 @@ roffparse(struct rofftree *tree, char *buf) return(0); } while (t != tokens[tok].ctx); - assert(tree->last); return(1); } @@ -940,7 +961,6 @@ roff_Os(ROFFCALL_ARGS) { if (ROFF_EXIT == type) { - roffnode_free(tree); return((*tree->cb.rofftail)(tree->arg)); } else if (ROFF_BODY & tree->state) { assert( ! (ROFF_PRELUDE & tree->state)); @@ -962,9 +982,6 @@ roff_Os(ROFFCALL_ARGS) tree->state |= ROFF_BODY; assert(NULL == tree->last); - - if (NULL == roffnode_new(tok, tree)) - return(0); return((*tree->cb.roffhead)(tree->arg)); }