If man(7) next-line scope is open and the line ends with \c,
authorschwarze <schwarze@openbsd.org>
Sat, 25 Aug 2018 12:28:52 +0000 (12:28 +0000)
committerschwarze <schwarze@openbsd.org>
Sat, 25 Aug 2018 12:28:52 +0000 (12:28 +0000)
the scope remains open.  Needed for example for groff_man(7).

regress/usr.bin/mandoc/roff/esc/c_man.in
regress/usr.bin/mandoc/roff/esc/c_man.out_ascii
usr.bin/mandoc/man.c

index c530a47..f6a5b0e 100644 (file)
@@ -1,15 +1,18 @@
-.\" $OpenBSD: c_man.in,v 1.3 2017/07/04 14:53:27 schwarze Exp $
-.TH ESC-C_MAN 1 "December 2, 2014"
+.\" $OpenBSD: c_man.in,v 1.4 2018/08/25 12:28:52 schwarze Exp $
+.TH ESC-C_MAN 1 "August 25, 2018"
 .SH NAME
 esc-c_man \- the roff escape c sequence: remove trailing space
 .SH DESCRIPTION
 No space between "one" and "word":
 one\c
 word
+.PP
+The same in no-fill mode:
 .nf
 one\c
 word
 .fi
+.PP
 Blank line after \ec:
 one\c
 
@@ -19,4 +22,16 @@ one\c
 
 word
 .fi
+.PP
+In next-line element scope:
+.B
+one\c
+word
+.PP
+In next-line block scope:
+.TP
+one\c
+word
+list body
+.PP
 final text
index 9062c33..a3a5088 100644 (file)
@@ -7,12 +7,23 @@ N\bNA\bAM\bME\bE
 
 D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
        No space between "one" and "word": oneword
+
+       The same in no-fill mode:
        oneword
+
        Blank line after \c: one word
        one
        word
+
+       In next-line element scope: o\bon\bne\bew\bwo\bor\brd\bd
+
+       In next-line block scope:
+
+       oneword
+              list body
+
        final text
 
 
 
-OpenBSD                        December 2, 2014                   ESC-C_MAN(1)
+OpenBSD                         August 25, 2018                   ESC-C_MAN(1)
index 7700248..7eb8458 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: man.c,v 1.126 2018/08/23 19:32:03 schwarze Exp $ */
+/*     $OpenBSD: man.c,v 1.127 2018/08/25 12:28:52 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2013,2014,2015,2017,2018 Ingo Schwarze <schwarze@openbsd.org>
@@ -33,7 +33,8 @@
 #include "roff_int.h"
 #include "libman.h"
 
-static void             man_descope(struct roff_man *, int, int);
+static void             man_descope(struct roff_man *, int, int, char *);
+static char            *man_hasc(char *);
 static int              man_ptext(struct roff_man *, int, char *, int);
 static int              man_pmacro(struct roff_man *, int, char *, int);
 
@@ -50,9 +51,32 @@ man_parseln(struct roff_man *man, int ln, char *buf, int offs)
            man_ptext(man, ln, buf, offs);
 }
 
+/*
+ * If the string ends with \c, return a pointer to the backslash.
+ * Otherwise, return NULL.
+ */
+static char *
+man_hasc(char *start)
+{
+       char    *cp, *ep;
+
+       ep = strchr(start, '\0') - 2;
+       if (ep < start || ep[0] != '\\' || ep[1] != 'c')
+               return NULL;
+       for (cp = ep; cp > start; cp--)
+               if (cp[-1] != '\\')
+                       break;
+       return (ep - cp) % 2 ? NULL : ep;
+}
+
 static void
-man_descope(struct roff_man *man, int line, int offs)
+man_descope(struct roff_man *man, int line, int offs, char *start)
 {
+       /* Trailing \c keeps next-line scope open. */
+
+       if (man_hasc(start) != NULL)
+               return;
+
        /*
         * Co-ordinate what happens with having a next-line scope open:
         * first close out the element scope (if applicable), then close
@@ -74,14 +98,13 @@ 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. */
 
        if (man->flags & MAN_LITERAL) {
                roff_word_alloc(man, line, offs, buf + offs);
-               man_descope(man, line, offs);
+               man_descope(man, line, offs, buf + offs);
                return 1;
        }
 
@@ -102,20 +125,10 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs)
                }
                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;
+               if (man->last->type == ROFFT_TEXT &&
+                   ((ep = man_hasc(man->last->string)) != NULL)) {
                        *ep = '\0';
                        return 1;
-               default:
-                       break;
                }
                roff_elem_alloc(man, line, offs, ROFF_sp);
                man->next = ROFF_NEXT_SIBLING;
@@ -155,7 +168,7 @@ man_ptext(struct roff_man *man, int line, char *buf, int offs)
        if (mandoc_eos(buf, (size_t)i))
                man->last->flags |= NODE_EOS;
 
-       man_descope(man, line, offs);
+       man_descope(man, line, offs, buf + offs);
        return 1;
 }