summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Schwarze <schwarze@openbsd.org>2015-02-02 04:26:44 +0000
committerIngo Schwarze <schwarze@openbsd.org>2015-02-02 04:26:44 +0000
commit5aa5efecc3c1ed935aac943e15689f4388db9bca (patch)
tree67ed1bdab37ed0d25bb60ac1d48a948dcb2b335d
parent2a8721309f4f7dbbb5908c122a134490432f4431 (diff)
downloadmandoc-5aa5efecc3c1ed935aac943e15689f4388db9bca.tar.gz
Get rid of all calls to rew_sub() in blk_exp_close(); only ten calls
remain in other functions. As a bonus, this fixes an assertion failure jsg@ found some time ago with afl (test case 982) and improves minor details in error reporting.
-rw-r--r--libmdoc.h2
-rw-r--r--mdoc.c3
-rw-r--r--mdoc_macro.c130
3 files changed, 69 insertions, 66 deletions
diff --git a/libmdoc.h b/libmdoc.h
index 22dd764c..da9aa615 100644
--- a/libmdoc.h
+++ b/libmdoc.h
@@ -106,7 +106,7 @@ struct mdoc_node *mdoc_block_alloc(struct mdoc *, int, int,
struct mdoc_node *mdoc_head_alloc(struct mdoc *, int, int, enum mdoct);
void mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct);
struct mdoc_node *mdoc_body_alloc(struct mdoc *, int, int, enum mdoct);
-void mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
+struct mdoc_node *mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct,
struct mdoc_node *, enum mdoc_endbody);
void mdoc_node_delete(struct mdoc *, struct mdoc_node *);
void mdoc_node_relink(struct mdoc *, struct mdoc_node *);
diff --git a/mdoc.c b/mdoc.c
index 5039a47d..9e7a1482 100644
--- a/mdoc.c
+++ b/mdoc.c
@@ -414,7 +414,7 @@ mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok)
return(p);
}
-void
+struct mdoc_node *
mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
struct mdoc_node *body, enum mdoc_endbody end)
{
@@ -426,6 +426,7 @@ mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok,
p->end = end;
node_append(mdoc, p);
mdoc->next = MDOC_NEXT_SIBLING;
+ return(p);
}
struct mdoc_node *
diff --git a/mdoc_macro.c b/mdoc_macro.c
index 8b3ea05b..e2b4d909 100644
--- a/mdoc_macro.c
+++ b/mdoc_macro.c
@@ -65,6 +65,7 @@ static enum rew rew_dohalt(enum mdoct, enum mdoc_type,
const struct mdoc_node *);
static void rew_elem(struct mdoc *, enum mdoct);
static void rew_last(struct mdoc *, const struct mdoc_node *);
+static void rew_pending(struct mdoc *, const struct mdoc_node *);
static void rew_sub(enum mdoc_type, struct mdoc *,
enum mdoct, int, int);
@@ -263,6 +264,9 @@ lookup(struct mdoc *mdoc, enum mdoct from, int line, int ppos, const char *p)
return(MDOC_MAX);
}
+/*
+ * Rewind up to and including a specific node.
+ */
static void
rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
{
@@ -271,6 +275,9 @@ rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
assert(to);
mdoc->next = MDOC_NEXT_SIBLING;
while (mdoc->last != to) {
+ if ( ! (mdoc->last->flags & MDOC_VALID))
+ mdoc->last->lastline = to->lastline -
+ (mdoc->flags & MDOC_NEWLINE ? 1 : 0);
/*
* Save the parent here, because we may delete the
* mdoc->last node in the post-validation phase and reset
@@ -288,6 +295,25 @@ rew_last(struct mdoc *mdoc, const struct mdoc_node *to)
}
/*
+ * Rewind up to a specific block, including all blocks that broke it.
+ */
+static void
+rew_pending(struct mdoc *mdoc, const struct mdoc_node *n)
+{
+
+ rew_last(mdoc, n);
+
+ if (n->type != MDOC_BLOCK)
+ return;
+
+ while ((n = n->pending) != NULL) {
+ rew_last(mdoc, n);
+ if (n->type == MDOC_HEAD)
+ mdoc_body_alloc(mdoc, n->line, n->pos, n->tok);
+ }
+}
+
+/*
* For a block closing macro, return the corresponding opening one.
* Otherwise, return the macro itself.
*/
@@ -533,6 +559,8 @@ make_pending(struct mdoc_node *broken, enum mdoct tok,
*/
broken->pending = breaker;
breaker->flags |= MDOC_BREAK;
+ if (breaker->body != NULL)
+ breaker->body->flags |= MDOC_BREAK;
mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos,
"%s breaks %s", mdoc_macronames[tok],
mdoc_macronames[broken->tok]);
@@ -592,17 +620,7 @@ rew_sub(enum mdoc_type t, struct mdoc *mdoc,
break;
}
assert(n);
- rew_last(mdoc, n);
-
- /*
- * The current block extends an enclosing block.
- * Now that the current block ends, close the enclosing block, too.
- */
- while ((n = n->pending) != NULL) {
- rew_last(mdoc, n);
- if (n->type == MDOC_HEAD)
- mdoc_body_alloc(mdoc, n->line, n->pos, n->tok);
- }
+ rew_pending(mdoc, n);
}
/*
@@ -716,9 +734,9 @@ blk_exp_close(MACRO_PROT_ARGS)
struct mdoc_node *body; /* Our own body. */
struct mdoc_node *endbody; /* Our own end marker. */
struct mdoc_node *later; /* A sub-block starting later. */
- struct mdoc_node *n; /* For searching backwards. */
+ struct mdoc_node *n; /* Search back to our block. */
- int flushed, have_it, j, lastarg, maxargs, nl;
+ int have_it, j, lastarg, maxargs, nl;
enum margserr ac;
enum mdoct atok, ntok;
char *p;
@@ -752,8 +770,10 @@ blk_exp_close(MACRO_PROT_ARGS)
/* Remember the start of our own body. */
if (n->type == MDOC_BODY && atok == n->tok) {
- if (n->end == ENDBODY_NOT)
+ if (n->end == ENDBODY_NOT) {
body = n;
+ n->lastline = line;
+ }
continue;
}
@@ -766,6 +786,7 @@ blk_exp_close(MACRO_PROT_ARGS)
}
if (atok == n->tok) {
+ n->lastline = line;
assert(body);
/*
@@ -791,20 +812,17 @@ blk_exp_close(MACRO_PROT_ARGS)
* the scope - of the current block ends.
*/
- mdoc_endbody_alloc(mdoc, line, ppos,
+ endbody = mdoc_endbody_alloc(mdoc, line, ppos,
atok, body, ENDBODY_SPACE);
/*
* If a block closing macro taking arguments
* breaks another block, put the arguments
- * into the end marker and remeber the
- * end marker in order to close it out.
+ * into the end marker.
*/
- if (maxargs) {
- endbody = mdoc->last;
+ if (maxargs)
mdoc->next = MDOC_NEXT_CHILD;
- }
break;
}
@@ -818,7 +836,23 @@ blk_exp_close(MACRO_PROT_ARGS)
! (mdoc_macros[later->tok].flags & MDOC_EXPLICIT))
later = n;
}
- rew_sub(MDOC_BODY, mdoc, tok, line, ppos);
+
+ if (body == NULL) {
+ mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse,
+ line, ppos, mdoc_macronames[tok]);
+ if (maxargs && endbody == NULL) {
+ /*
+ * Stray .Ec without previous .Eo:
+ * Break the output line, keep the arguments.
+ */
+ mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL);
+ rew_elem(mdoc, MDOC_br);
+ }
+ } else if (endbody == NULL) {
+ rew_last(mdoc, body);
+ if (maxargs)
+ mdoc_tail_alloc(mdoc, line, ppos, atok);
+ }
if ( ! (mdoc_macros[tok].flags & MDOC_PARSED)) {
if (buf[*pos] != '\0')
@@ -830,28 +864,14 @@ blk_exp_close(MACRO_PROT_ARGS)
return;
}
- if (maxargs && endbody == NULL) {
- if (n == NULL) {
- /*
- * Stray .Ec without previous .Eo:
- * Break the output line, ignore any arguments.
- */
- mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL);
- rew_elem(mdoc, MDOC_br);
- } else
- mdoc_tail_alloc(mdoc, line, ppos, atok);
- }
-
- flushed = n == NULL;
+ if (endbody != NULL)
+ n = endbody;
for (j = 0; ; j++) {
lastarg = *pos;
- if (j == maxargs && ! flushed) {
- if (endbody == NULL)
- rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
- else
- rew_last(mdoc, endbody);
- flushed = 1;
+ if (j == maxargs && n != NULL) {
+ rew_pending(mdoc, n);
+ n = NULL;
}
ac = mdoc_args(mdoc, line, pos, buf, tok, &p);
@@ -867,24 +887,17 @@ blk_exp_close(MACRO_PROT_ARGS)
continue;
}
- if ( ! flushed) {
- if (endbody == NULL)
- rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
- else
- rew_last(mdoc, endbody);
- flushed = 1;
+ if (n != NULL) {
+ rew_pending(mdoc, n);
+ n = NULL;
}
mdoc->flags &= ~MDOC_NEWLINE;
mdoc_macro(mdoc, ntok, line, lastarg, pos, buf);
break;
}
- if ( ! flushed) {
- if (endbody == NULL)
- rew_sub(MDOC_BLOCK, mdoc, tok, line, ppos);
- else
- rew_last(mdoc, endbody);
- }
+ if (n != NULL)
+ rew_pending(mdoc, n);
if (nl)
append_delims(mdoc, line, pos, buf);
}
@@ -1327,18 +1340,7 @@ blk_part_imp(MACRO_PROT_ARGS)
rew_last(mdoc, body);
if (nl)
append_delims(mdoc, line, pos, buf);
- rew_last(mdoc, blk);
-
- /*
- * The current block extends an enclosing block.
- * Now that the current block ends, close the enclosing block, too.
- */
-
- while ((blk = blk->pending) != NULL) {
- rew_last(mdoc, blk);
- if (blk->type == MDOC_HEAD)
- mdoc_body_alloc(mdoc, blk->line, blk->pos, blk->tok);
- }
+ rew_pending(mdoc, blk);
/* Move trailing .Ns out of scope. */