diff options
-rw-r--r-- | mdoc.c | 6 | ||||
-rw-r--r-- | mdoc.h | 8 | ||||
-rw-r--r-- | mdoc_html.c | 9 | ||||
-rw-r--r-- | mdoc_macro.c | 186 | ||||
-rw-r--r-- | mdoc_man.c | 17 | ||||
-rw-r--r-- | mdoc_term.c | 5 | ||||
-rw-r--r-- | mdoc_validate.c | 44 |
7 files changed, 108 insertions, 167 deletions
@@ -1,7 +1,7 @@ /* $Id$ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -419,8 +419,10 @@ mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok, { struct mdoc_node *p; + body->flags |= MDOC_ENDED; + body->parent->flags |= MDOC_ENDED; p = node_alloc(mdoc, line, pos, tok, MDOC_BODY); - p->pending = body; + p->body = body; p->norm = body->norm; p->end = end; node_append(mdoc, p); @@ -1,6 +1,7 @@ /* $Id$ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -355,11 +356,11 @@ struct mdoc_node { enum mdoct tok; /* tok or MDOC__MAX if none */ int flags; #define MDOC_VALID (1 << 0) /* has been validated */ -#define MDOC_BREAK (1 << 1) /* has broken another block */ +#define MDOC_ENDED (1 << 1) /* gone past body end mark */ #define MDOC_EOS (1 << 2) /* at sentence boundary */ #define MDOC_LINE (1 << 3) /* first macro/text on line */ #define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting */ -#define MDOC_ENDED (1 << 5) /* rendering has been ended */ +#define MDOC_BROKEN (1 << 5) /* must validate parent when ending */ #define MDOC_DELIMO (1 << 6) #define MDOC_DELIMC (1 << 7) enum mdoc_type type; /* AST node type */ @@ -368,9 +369,8 @@ struct mdoc_node { int prev_font; /* before entering this node */ /* FIXME: these can be union'd to shave a few bytes. */ struct mdoc_arg *args; /* BLOCK/ELEM */ - struct mdoc_node *pending; /* BLOCK */ struct mdoc_node *head; /* BLOCK */ - struct mdoc_node *body; /* BLOCK */ + struct mdoc_node *body; /* BLOCK/ENDBODY */ struct mdoc_node *tail; /* BLOCK */ char *string; /* TEXT */ const struct tbl_span *span; /* TBL */ diff --git a/mdoc_html.c b/mdoc_html.c index 067cfabd..bff01cf2 100644 --- a/mdoc_html.c +++ b/mdoc_html.c @@ -35,7 +35,7 @@ #define INDENT 5 #define MDOC_ARGS const struct mdoc_meta *meta, \ - const struct mdoc_node *n, \ + struct mdoc_node *n, \ struct html *h #ifndef MIN @@ -267,7 +267,7 @@ void html_mdoc(void *arg, const struct mdoc *mdoc) { - print_mdoc(mdoc_meta(mdoc), mdoc_node(mdoc), + print_mdoc(mdoc_meta(mdoc), mdoc_node(mdoc)->child, (struct html *)arg); putchar('\n'); } @@ -387,6 +387,7 @@ print_mdoc_node(MDOC_ARGS) child = 1; t = h->tags.head; + n->flags &= ~MDOC_ENDED; switch (n->type) { case MDOC_ROOT: @@ -457,7 +458,7 @@ print_mdoc_node(MDOC_ARGS) break; (*mdocs[n->tok].post)(meta, n, h); if (n->end != ENDBODY_NOT) - n->pending->flags |= MDOC_ENDED; + n->body->flags |= MDOC_ENDED; if (n->end == ENDBODY_NOSPACE) h->flags |= HTML_NOSPACE; break; @@ -1122,7 +1123,7 @@ mdoc_bd_pre(MDOC_ARGS) { struct htmlpair tag[2]; int comp, sv; - const struct mdoc_node *nn; + struct mdoc_node *nn; struct roffsu su; if (MDOC_HEAD == n->type) diff --git a/mdoc_macro.c b/mdoc_macro.c index 03317c72..bd98e583 100644 --- a/mdoc_macro.c +++ b/mdoc_macro.c @@ -47,8 +47,6 @@ static void append_delims(struct mdoc *, int, int *, char *); static enum mdoct lookup(struct mdoc *, enum mdoct, int, int, const char *); static int macro_or_word(MACRO_PROT_ARGS, int); -static void make_pending(struct mdoc *, struct mdoc_node *, - struct mdoc_node *, int, int); static int parse_rest(struct mdoc *, enum mdoct, int, int *, char *); static enum mdoct rew_alt(enum mdoct); @@ -285,15 +283,34 @@ 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) { + for (;;) { rew_last(mdoc, n); - if (n->type == MDOC_HEAD) + + switch (n->type) { + case MDOC_HEAD: mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); + return; + case MDOC_BLOCK: + break; + default: + return; + } + + if ( ! (n->flags & MDOC_BROKEN)) + return; + + for (;;) { + if ((n = n->parent) == NULL) + return; + + if (n->type == MDOC_BLOCK || + n->type == MDOC_HEAD) { + if (n->flags & MDOC_ENDED) + break; + else + return; + } + } } } @@ -357,78 +374,6 @@ rew_elem(struct mdoc *mdoc, enum mdoct tok) } /* - * We are trying to close the block *breaker, - * but the child block *broken is still open. - * Thus, postpone closing the *breaker - * until the rew_pending() call closing *broken. - */ -static void -make_pending(struct mdoc *mdoc, struct mdoc_node *breaker, - struct mdoc_node *broken, int line, int ppos) -{ - struct mdoc_node *n; - - mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, line, ppos, - "%s breaks %s", mdoc_macronames[breaker->tok], - mdoc_macronames[broken->tok]); - - /* - * If the *broken block (Z) is already broken by a block (B) - * contained in the breaker (A), make the breaker pending - * on that inner breaker (B). Graphically, - * - * breaker=[A! broken=n=[B!->A (old broken=)[Z->B B] A] Z] - * - * In these graphics, "->" indicates the "pending" pointer and - * "!" indicates the MDOC_BREAK flag. Each of the cases gets - * one additional pointer (B->A) and one additional flag (A!). - */ - - for (n = broken->parent; ; n = n->parent) - if (n == broken->pending) - broken = n; - else if (n == breaker) - break; - - /* - * Found the breaker. - * - * If another, outer breaker (X) is already pending on - * the *broken block (B), we must not clobber the link - * to the outer breaker, but make it pending on the new, - * now inner breaker (A). Graphically, - * - * [X! n=breaker=[A!->X broken=[B(->X)->A X] A] B]. - */ - - if (broken->pending != NULL) { - n = breaker; - - /* - * If the inner breaker (A) is already broken, too, - * it cannot take on the outer breaker (X) but must - * hand it on to its own breakers (Y). Graphically, - * - * [X! n=[Y!->X breaker=[A!->Y Y] broken=[B(->X)->A X] A] B] - */ - - while (n->pending) - n = n->pending; - n->pending = broken->pending; - } - - /* - * Now we have reduced the situation to the simplest case: - * breaker=[A! broken=[B->A A] B]. - */ - - broken->pending = breaker; - breaker->flags |= MDOC_BREAK; - if (breaker->body != NULL) - breaker->body->flags |= MDOC_BREAK; -} - -/* * Allocate a word and check whether it's punctuation or not. * Punctuation consists of those tokens found in mdoc_isdelim(). */ @@ -569,8 +514,11 @@ blk_exp_close(MACRO_PROT_ARGS) atok = rew_alt(tok); body = endbody = itblk = later = NULL; for (n = mdoc->last; n; n = n->parent) { - if (n->flags & (MDOC_VALID | MDOC_BREAK)) + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; continue; + } /* Remember the start of our own body. */ @@ -605,20 +553,21 @@ blk_exp_close(MACRO_PROT_ARGS) * When there is a pending sub block, postpone * closing out the current block until the * rew_pending() closing out the sub-block. - */ - - make_pending(mdoc, n, later, line, ppos); - if (tok == MDOC_El) - itblk->flags |= MDOC_BREAK; - - /* * Mark the place where the formatting - but not * the scope - of the current block ends. */ + mandoc_vmsg(MANDOCERR_BLK_NEST, mdoc->parse, + line, ppos, "%s breaks %s", + mdoc_macronames[atok], + mdoc_macronames[later->tok]); + endbody = mdoc_endbody_alloc(mdoc, line, ppos, atok, body, ENDBODY_SPACE); + if (tok == MDOC_El) + itblk->flags |= MDOC_ENDED | MDOC_BROKEN; + /* * If a block closing macro taking arguments * breaks another block, put the arguments @@ -637,14 +586,10 @@ blk_exp_close(MACRO_PROT_ARGS) continue; } - /* - * When finding an open sub block, remember the last - * open explicit block, or, in case there are only - * implicit ones, the first open implicit block. - */ + /* Breaking an open sub block. */ - if (later == NULL || - ! (mdoc_macros[later->tok].flags & MDOC_EXPLICIT)) + n->flags |= MDOC_BROKEN; + if (later == NULL) later = n; } @@ -923,9 +868,14 @@ blk_full(MACRO_PROT_ARGS) blk = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { - if (n->flags & (MDOC_VALID | MDOC_BREAK) || - n->type != MDOC_BLOCK) + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; + continue; + } + if (n->type != MDOC_BLOCK) continue; + if (tok == MDOC_It && n->tok == MDOC_Bl) { if (blk != NULL) { mandoc_vmsg(MANDOCERR_BLK_BROKEN, @@ -1131,13 +1081,19 @@ blk_full(MACRO_PROT_ARGS) * sub-block. */ for (n = mdoc->last; n && n != head; n = n->parent) { + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; + continue; + } if (n->type == MDOC_BLOCK && - mdoc_macros[n->tok].flags & MDOC_EXPLICIT && - ! (n->flags & MDOC_VALID)) { - n->pending = head; - return; + mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { + n->flags = MDOC_BROKEN; + head->flags = MDOC_ENDED; } } + if (head->flags & MDOC_ENDED) + return; /* Close out scopes to remain in a consistent state. */ @@ -1210,16 +1166,28 @@ blk_part_imp(MACRO_PROT_ARGS) for (n = mdoc->last; n && n != body && n != blk->parent; n = n->parent) { + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; + continue; + } if (n->type == MDOC_BLOCK && - mdoc_macros[n->tok].flags & MDOC_EXPLICIT && - ! (n->flags & MDOC_VALID)) { - make_pending(mdoc, blk, n, line, ppos); - mdoc_endbody_alloc(mdoc, line, ppos, - tok, body, ENDBODY_NOSPACE); - return; + mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { + n->flags |= MDOC_BROKEN; + if ( ! (body->flags & MDOC_ENDED)) { + mandoc_vmsg(MANDOCERR_BLK_NEST, + mdoc->parse, line, ppos, + "%s breaks %s", mdoc_macronames[tok], + mdoc_macronames[n->tok]); + mdoc_endbody_alloc(mdoc, line, ppos, + tok, body, ENDBODY_NOSPACE); + } } } assert(n == body); + if (body->flags & MDOC_ENDED) + return; + rew_last(mdoc, body); if (nl) append_delims(mdoc, line, pos, buf); @@ -1482,7 +1450,7 @@ phrase_ta(MACRO_PROT_ARGS) body = NULL; for (n = mdoc->last; n != NULL; n = n->parent) { - if (n->flags & (MDOC_VALID | MDOC_BREAK)) + if (n->flags & MDOC_ENDED) continue; if (n->tok == MDOC_It && n->type == MDOC_BODY) body = n; @@ -29,8 +29,7 @@ #include "mdoc.h" #include "main.h" -#define DECL_ARGS const struct mdoc_meta *meta, \ - const struct mdoc_node *n +#define DECL_ARGS const struct mdoc_meta *meta, struct mdoc_node *n struct manact { int (*cond)(DECL_ARGS); /* DON'T run actions */ @@ -548,10 +547,10 @@ void man_mdoc(void *arg, const struct mdoc *mdoc) { const struct mdoc_meta *meta; - const struct mdoc_node *n; + struct mdoc_node *n; meta = mdoc_meta(mdoc); - n = mdoc_node(mdoc); + n = mdoc_node(mdoc)->child; printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", meta->title, @@ -567,15 +566,18 @@ man_mdoc(void *arg, const struct mdoc *mdoc) fontqueue.head = fontqueue.tail = mandoc_malloc(8); *fontqueue.tail = 'R'; } - print_node(meta, n); + while (n != NULL) { + print_node(meta, n); + n = n->next; + } putchar('\n'); } static void print_node(DECL_ARGS) { - const struct mdoc_node *sub; const struct manact *act; + struct mdoc_node *sub; int cond, do_sub; /* @@ -588,6 +590,7 @@ print_node(DECL_ARGS) act = NULL; cond = 0; do_sub = 1; + n->flags &= ~MDOC_ENDED; if (MDOC_TEXT == n->type) { /* @@ -635,7 +638,7 @@ print_node(DECL_ARGS) (*act->post)(meta, n); if (ENDBODY_NOT != n->end) - n->pending->flags |= MDOC_ENDED; + n->body->flags |= MDOC_ENDED; if (ENDBODY_NOSPACE == n->end) outflags &= ~(MMAN_spc | MMAN_nl); diff --git a/mdoc_term.c b/mdoc_term.c index 1b5ce429..5f4f6a43 100644 --- a/mdoc_term.c +++ b/mdoc_term.c @@ -309,6 +309,7 @@ print_mdoc_node(DECL_ARGS) chld = 1; offset = p->offset; rmargin = p->rmargin; + n->flags &= ~MDOC_ENDED; n->prev_font = p->fonti; memset(&npair, 0, sizeof(struct termpair)); @@ -361,7 +362,7 @@ print_mdoc_node(DECL_ARGS) print_mdoc_nodelist(p, &npair, meta, n->child); term_fontpopq(p, - (ENDBODY_NOT == n->end ? n : n->pending)->prev_font); + (ENDBODY_NOT == n->end ? n : n->body)->prev_font); switch (n->type) { case MDOC_TEXT: @@ -381,7 +382,7 @@ print_mdoc_node(DECL_ARGS) * that it must not call the post handler again. */ if (ENDBODY_NOT != n->end) - n->pending->flags |= MDOC_ENDED; + n->body->flags |= MDOC_ENDED; /* * End of line terminating an implicit block diff --git a/mdoc_validate.c b/mdoc_validate.c index 94e36d9f..21948506 100644 --- a/mdoc_validate.c +++ b/mdoc_validate.c @@ -325,7 +325,7 @@ mdoc_valid_post(struct mdoc *mdoc) n = mdoc->last; if (n->flags & MDOC_VALID) return; - n->flags |= MDOC_VALID; + n->flags |= MDOC_VALID | MDOC_ENDED; switch (n->type) { case MDOC_TEXT: @@ -416,24 +416,13 @@ pre_display(PRE_ARGS) static void pre_bl(PRE_ARGS) { - struct mdoc_node *np; struct mdoc_argv *argv, *wa; int i; enum mdocargt mdoclt; enum mdoc_list lt; - if (MDOC_BLOCK != n->type) { - if (ENDBODY_NOT != n->end) { - assert(n->pending); - np = n->pending->parent; - } else - np = n->parent; - - assert(np); - assert(MDOC_BLOCK == np->type); - assert(MDOC_Bl == np->tok); + if (n->type != MDOC_BLOCK) return; - } /* * First figure out which kind of list to use: bind ourselves to @@ -609,25 +598,14 @@ pre_bl(PRE_ARGS) static void pre_bd(PRE_ARGS) { - struct mdoc_node *np; struct mdoc_argv *argv; int i; enum mdoc_disp dt; pre_literal(mdoc, n); - if (MDOC_BLOCK != n->type) { - if (ENDBODY_NOT != n->end) { - assert(n->pending); - np = n->pending->parent; - } else - np = n->parent; - - assert(np); - assert(MDOC_BLOCK == np->type); - assert(MDOC_Bd == np->tok); + if (n->type != MDOC_BLOCK) return; - } for (i = 0; n->args && i < (int)n->args->argc; i++) { argv = n->args->argv + i; @@ -797,22 +775,10 @@ post_bf(POST_ARGS) * element, which contains the goods. */ - if (MDOC_HEAD != mdoc->last->type) { - if (ENDBODY_NOT != mdoc->last->end) { - assert(mdoc->last->pending); - np = mdoc->last->pending->parent->head; - } else if (MDOC_BLOCK != mdoc->last->type) { - np = mdoc->last->parent->head; - } else - np = mdoc->last->head; - - assert(np); - assert(MDOC_HEAD == np->type); - assert(MDOC_Bf == np->tok); + np = mdoc->last; + if (MDOC_HEAD != np->type) return; - } - np = mdoc->last; assert(MDOC_BLOCK == np->parent->type); assert(MDOC_Bf == np->parent->tok); |