From 8b829c3fb9f3b6e04849fd535eeb826b618e533a Mon Sep 17 00:00:00 2001 From: Ingo Schwarze Date: Sat, 17 Jun 2017 13:06:16 +0000 Subject: correct handling of blank lines after \c --- man.c | 33 ++++++++++++++++++++++++++------- man_term.c | 5 ++++- mdoc.c | 28 ++++++++++++++++++++++------ regress/roff/esc/c.in | 9 +++++++++ regress/roff/esc/c.out_ascii | 4 ++++ regress/roff/esc/c_man.in | 9 +++++++++ regress/roff/esc/c_man.out_ascii | 3 +++ 7 files changed, 77 insertions(+), 14 deletions(-) diff --git a/man.c b/man.c index 971b15bf..9ca3e0ea 100644 --- a/man.c +++ b/man.c @@ -76,6 +76,8 @@ static int man_ptext(struct roff_man *man, int line, char *buf, int offs) { int i; + const char *cp, *sp; + char *ep; /* Literal free-form text whitespace is preserved. */ @@ -89,19 +91,36 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs) /* Skip leading whitespace. */ ; /* - * Blank lines are ignored in next line scope and right - * after headings but add a single vertical space elsewhere. + * Blank lines are ignored in next line scope + * and right after headings and cancel preceding \c, + * but add a single vertical space elsewhere. */ if (buf[i] == '\0') { - if (man->flags & (MAN_ELINE | MAN_BLINE)) + if (man->flags & (MAN_ELINE | MAN_BLINE)) { mandoc_msg(MANDOCERR_BLK_BLANK, man->parse, line, 0, NULL); - else if (man->last->tok != MAN_SH && - man->last->tok != MAN_SS) { - roff_elem_alloc(man, line, offs, ROFF_sp); - man->next = ROFF_NEXT_SIBLING; + return 1; } + if (man->last->tok == MAN_SH || man->last->tok == MAN_SS) + return 1; + switch (man->last->type) { + case ROFFT_TEXT: + sp = man->last->string; + cp = ep = strchr(sp, '\0') - 2; + if (cp < sp || cp[0] != '\\' || cp[1] != 'c') + break; + while (cp > sp && cp[-1] == '\\') + cp--; + if ((ep - cp) % 2) + break; + *ep = '\0'; + return 1; + default: + break; + } + roff_elem_alloc(man, line, offs, ROFF_sp); + man->next = ROFF_NEXT_SIBLING; return 1; } diff --git a/man_term.c b/man_term.c index 5f527721..f317aadf 100644 --- a/man_term.c +++ b/man_term.c @@ -872,7 +872,10 @@ print_man_node(DECL_ARGS) * before printing the line's data. */ if (*n->string == '\0') { - term_vspace(p); + if (p->flags & TERMP_NONEWLINE) + term_newln(p); + else + term_vspace(p); return; } else if (*n->string == ' ' && n->flags & NODE_LINE && (p->flags & TERMP_NONEWLINE) == 0) diff --git a/mdoc.c b/mdoc.c index 4794b0d9..c98cfb15 100644 --- a/mdoc.c +++ b/mdoc.c @@ -179,6 +179,7 @@ static int mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs) { struct roff_node *n; + const char *cp, *sp; char *c, *ws, *end; n = mdoc->last; @@ -244,15 +245,30 @@ mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs) mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, line, (int)(ws-buf), NULL); + /* + * Blank lines are allowed in no-fill mode + * and cancel preceding \c, + * but add a single vertical space elsewhere. + */ + if (buf[offs] == '\0' && ! (mdoc->flags & MDOC_LITERAL)) { + switch (mdoc->last->type) { + case ROFFT_TEXT: + sp = mdoc->last->string; + cp = end = strchr(sp, '\0') - 2; + if (cp < sp || cp[0] != '\\' || cp[1] != 'c') + break; + while (cp > sp && cp[-1] == '\\') + cp--; + if ((end - cp) % 2) + break; + *end = '\0'; + return 1; + default: + break; + } mandoc_msg(MANDOCERR_FI_BLANK, mdoc->parse, line, (int)(c - buf), NULL); - - /* - * Insert a `sp' in the case of a blank line. Technically, - * blank lines aren't allowed, but enough manuals assume this - * behaviour that we want to work around it. - */ roff_elem_alloc(mdoc, line, offs, ROFF_sp); mdoc->last->flags |= NODE_VALID | NODE_ENDED; mdoc->next = ROFF_NEXT_SIBLING; diff --git a/regress/roff/esc/c.in b/regress/roff/esc/c.in index c3b7a912..b7b47bc1 100644 --- a/regress/roff/esc/c.in +++ b/regress/roff/esc/c.in @@ -15,3 +15,12 @@ word one\c word .Ed +Blank line after \ec: +one\c + +word +.Bd -literal +one\c + +word +.Ed diff --git a/regress/roff/esc/c.out_ascii b/regress/roff/esc/c.out_ascii index a0f6a996..9f8570c4 100644 --- a/regress/roff/esc/c.out_ascii +++ b/regress/roff/esc/c.out_ascii @@ -7,5 +7,9 @@ DDEESSCCRRIIPPTTIIOONN No space between "one" and "word": oneword oneword + Blank line after \c: one word + + one + word OpenBSD December 2, 2014 OpenBSD diff --git a/regress/roff/esc/c_man.in b/regress/roff/esc/c_man.in index c18fad10..09e1ed3b 100644 --- a/regress/roff/esc/c_man.in +++ b/regress/roff/esc/c_man.in @@ -7,6 +7,15 @@ one\c word .nf one\c +word +.fi +Blank line after \ec: +one\c + +word +.nf +one\c + word .fi final text diff --git a/regress/roff/esc/c_man.out_ascii b/regress/roff/esc/c_man.out_ascii index d00b1b48..9062c335 100644 --- a/regress/roff/esc/c_man.out_ascii +++ b/regress/roff/esc/c_man.out_ascii @@ -8,6 +8,9 @@ NNAAMMEE DDEESSCCRRIIPPTTIIOONN No space between "one" and "word": oneword oneword + Blank line after \c: one word + one + word final text -- cgit