Import mdocml-1.12.3 vendor/MDOCML
authorFranco Fichtner <franco@lastsummer.de>
Tue, 31 Dec 2013 13:10:20 +0000 (14:10 +0100)
committerFranco Fichtner <franco@lastsummer.de>
Tue, 31 Dec 2013 13:10:20 +0000 (14:10 +0100)
39 files changed:
contrib/mdocml/Makefile
contrib/mdocml/NEWS
contrib/mdocml/TODO
contrib/mdocml/apropos_db.c
contrib/mdocml/catman.c
contrib/mdocml/cgi.c
contrib/mdocml/config.h.post
contrib/mdocml/index.sgml
contrib/mdocml/lib.in
contrib/mdocml/libmandoc.h
contrib/mdocml/libmdoc.h
contrib/mdocml/man.c
contrib/mdocml/man.h
contrib/mdocml/man_html.c
contrib/mdocml/man_macro.c
contrib/mdocml/man_term.c
contrib/mdocml/man_validate.c
contrib/mdocml/mandoc.3
contrib/mdocml/mandoc.c
contrib/mdocml/mandoc.h
contrib/mdocml/mandoc_char.7
contrib/mdocml/mandocdb.c
contrib/mdocml/manpath.c
contrib/mdocml/mdoc.7
contrib/mdocml/mdoc.c
contrib/mdocml/mdoc.h
contrib/mdocml/mdoc_argv.c
contrib/mdocml/mdoc_html.c
contrib/mdocml/mdoc_macro.c
contrib/mdocml/mdoc_man.c
contrib/mdocml/mdoc_term.c
contrib/mdocml/mdoc_validate.c
contrib/mdocml/out.c
contrib/mdocml/roff.7
contrib/mdocml/roff.c
contrib/mdocml/st.in
contrib/mdocml/term.c
contrib/mdocml/term.h
contrib/mdocml/tree.c

index 044d087..20b9fea 100644 (file)
@@ -8,8 +8,8 @@
 #
 # CFLAGS       += -DOSNAME="\"OpenBSD 5.4\""
 
 #
 # CFLAGS       += -DOSNAME="\"OpenBSD 5.4\""
 
-VERSION                 = 1.12.2
-VDATE           = 05 October 2013
+VERSION                 = 1.12.3
+VDATE           = 31 December 2013
 
 # IFF your system supports multi-byte functions (setlocale(), wcwidth(),
 # putwchar()) AND has __STDC_ISO_10646__ (that is, wchar_t is simply a
 
 # IFF your system supports multi-byte functions (setlocale(), wcwidth(),
 # putwchar()) AND has __STDC_ISO_10646__ (that is, wchar_t is simply a
@@ -31,7 +31,7 @@ STATIC                 = -static
 # Linux requires -pthread to statically link with libdb.
 #STATIC                += -pthread
 
 # Linux requires -pthread to statically link with libdb.
 #STATIC                += -pthread
 
-CFLAGS         += -g -DHAVE_CONFIG_H -DVERSION="\"$(VERSION)\""
+CFLAGS         += -g -DHAVE_CONFIG_H
 CFLAGS         += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
 PREFIX          = /usr/local
 WWWPREFIX       = /var/www
 CFLAGS         += -W -Wall -Wstrict-prototypes -Wno-unused-parameter -Wwrite-strings
 PREFIX          = /usr/local
 WWWPREFIX       = /var/www
@@ -390,31 +390,32 @@ config.h: config.h.pre config.h.post
        rm -f config.log
        ( cat config.h.pre; \
          echo; \
        rm -f config.log
        ( cat config.h.pre; \
          echo; \
-         if $(CC) $(CFLAGS) -Werror -o test-fgetln test-fgetln.c >> config.log 2>&1; then \
+         echo '#define VERSION "$(VERSION)"'; \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-fgetln test-fgetln.c >> config.log 2>&1; then \
                echo '#define HAVE_FGETLN'; \
                rm test-fgetln; \
          fi; \
                echo '#define HAVE_FGETLN'; \
                rm test-fgetln; \
          fi; \
-         if $(CC) $(CFLAGS) -Werror -o test-strptime test-strptime.c >> config.log 2>&1; then \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strptime test-strptime.c >> config.log 2>&1; then \
                echo '#define HAVE_STRPTIME'; \
                rm test-strptime; \
          fi; \
                echo '#define HAVE_STRPTIME'; \
                rm test-strptime; \
          fi; \
-         if $(CC) $(CFLAGS) -Werror -o test-getsubopt test-getsubopt.c >> config.log 2>&1; then \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-getsubopt test-getsubopt.c >> config.log 2>&1; then \
                echo '#define HAVE_GETSUBOPT'; \
                rm test-getsubopt; \
          fi; \
                echo '#define HAVE_GETSUBOPT'; \
                rm test-getsubopt; \
          fi; \
-         if $(CC) $(CFLAGS) -Werror -o test-strlcat test-strlcat.c >> config.log 2>&1; then \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strlcat test-strlcat.c >> config.log 2>&1; then \
                echo '#define HAVE_STRLCAT'; \
                rm test-strlcat; \
          fi; \
                echo '#define HAVE_STRLCAT'; \
                rm test-strlcat; \
          fi; \
-         if $(CC) $(CFLAGS) -Werror -o test-mmap test-mmap.c >> config.log 2>&1; then \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-mmap test-mmap.c >> config.log 2>&1; then \
                echo '#define HAVE_MMAP'; \
                rm test-mmap; \
          fi; \
                echo '#define HAVE_MMAP'; \
                rm test-mmap; \
          fi; \
-         if $(CC) $(CFLAGS) -Werror -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-strlcpy test-strlcpy.c >> config.log 2>&1; then \
                echo '#define HAVE_STRLCPY'; \
                rm test-strlcpy; \
          fi; \
                echo '#define HAVE_STRLCPY'; \
                rm test-strlcpy; \
          fi; \
-         if $(CC) $(CFLAGS) -Werror -o test-betoh64 test-betoh64.c >> config.log 2>&1; then \
+         if $(CC) $(CFLAGS) -Werror -Wno-unused -o test-betoh64 test-betoh64.c >> config.log 2>&1; then \
                echo '#define HAVE_BETOH64'; \
                rm test-betoh64; \
          fi; \
                echo '#define HAVE_BETOH64'; \
                rm test-betoh64; \
          fi; \
index 784b89b..6f21a38 100644 (file)
@@ -1,7 +1,35 @@
-$Id: NEWS,v 1.2 2013/10/05 13:15:51 schwarze Exp $
+$Id: NEWS,v 1.3 2013/10/13 16:06:50 schwarze Exp $
 
 This file lists the most important changes in the mdocml.bsd.lv distribution.
 
 
 This file lists the most important changes in the mdocml.bsd.lv distribution.
 
+Changes in version 1.12.3, released on December 31, 2013
+
+ * In the mdoc(7) SYNOPSIS, line breaks and hanging indentation
+   now work correctly for .Fo/.Fa/.Fc and .Fn blocks.
+   Thanks to Franco Fichtner for doing part of the work.
+ * The mdoc(7) .Bk macro got some addititonal bugfixes.
+ * In mdoc(7) macro arguments, double quotes can now be quoted
+   by doubling them, just like in man(7).
+   Thanks to Tsugutomo ENAMI for the patch.
+ * At the end of man(7) macro lines, end-of-sentence spacing
+   now works.  Thanks to Franco Fichtner for the patch.
+ * For backward compatibility, the man(7) parser now supports the
+   man-ext .UR/.UE (uniform resource identifier) block macros.
+ * The man(7) parser now handles closing blocks that are not open
+   more gracefully.
+ * The man(7) parser now ignores blank lines right after .SH and .SS.
+ * In the man(7) formatter, reset indentation when leaving a block,
+   not just when entering the next one.
+ * The roff(7) .nr request now supports incrementing and decrementing
+   number registers and stops parsing the number right before the
+   first non-digit character.
+ * The roff(7) parser now supports the alternative escape sequence
+   syntax \C'uXXXX' for Unicode characters.
+ * The roff(7) parser now parses and ignores the .fam (font family)
+   and .hw (hyphenation points) requests and the \d and \u escape
+   sequences.
+ * The roff(7) manual got a new ESCAPE SEQUENCE REFERENCE.
+
 Changes in version 1.12.2, released on Oktober 5, 2013
 
  * The mdoc(7) to man(7) converter, to be called as mandoc -Tman,
 Changes in version 1.12.2, released on Oktober 5, 2013
 
  * The mdoc(7) to man(7) converter, to be called as mandoc -Tman,
@@ -130,13 +158,16 @@ Changes in version 1.11.1, released on April 4, 2011
  * The earlier libroff, libmdoc, and libman soup have been merged into
    a single library, libmandoc, which manages all aspects of parsing
    real manuals, from line-handling to tbl(7) parsing.
  * The earlier libroff, libmdoc, and libman soup have been merged into
    a single library, libmandoc, which manages all aspects of parsing
    real manuals, from line-handling to tbl(7) parsing.
- * Beyond this structural change, initial eqn(7) functionality is in
-   place.  For the time being, this is limited to the recognition of
-   equation blocks; future version of mdocml will expand upon this
-   framework.
  * As usual, many general fixes and improvements have also occurred.
    In particular, a great deal of redundancy and superfluous code has
    been removed with the merging of the backend libraries.
  * As usual, many general fixes and improvements have also occurred.
    In particular, a great deal of redundancy and superfluous code has
    been removed with the merging of the backend libraries.
+ * see also the changes in 1.10.10
+
+Changes in version 1.10.10, March 20, 2011, NOT released
+
+ * Initial eqn(7) functionality is in place.  For the time being,
+   this is limited to the recognition of equation blocks;
+   future version of mdocml will expand upon this framework.
 
 Changes in version 1.10.9, released on January 7, 2011
 
 
 Changes in version 1.10.9, released on January 7, 2011
 
@@ -150,19 +181,23 @@ Changes in version 1.10.9, released on January 7, 2011
 
 Changes in version 1.10.8, released on December 24, 2010
 
 
 Changes in version 1.10.8, released on December 24, 2010
 
- * Significant improvements merged from OpenBSD downstream, including
-    - many new roff(7) components,
-    - in-line implementation of troff's soelim(1),
-    - broken-block handling,
-    - overhauled error classifications, and
-    - cleaned up handling of error conditions.
- * Also overhauled the -Thtml and -Txhtml output modes.  They now display
+ * Overhauled the -Thtml and -Txhtml output modes.  They now display
    readable output in arbitrary browsers, including text-based ones like
    lynx(1).  See HTML and XHTML manuals in the DOCUMENTATION section
    for examples.  Attention: available style-sheet classes have been
    considerably changed!  See the example.style.css file for details.
    Lastly, libmdoc and libman have been cleaned up and reduced in size
    and complexity.
    readable output in arbitrary browsers, including text-based ones like
    lynx(1).  See HTML and XHTML manuals in the DOCUMENTATION section
    for examples.  Attention: available style-sheet classes have been
    considerably changed!  See the example.style.css file for details.
    Lastly, libmdoc and libman have been cleaned up and reduced in size
    and complexity.
+ * see also the changes in 1.10.7
+
+Changes in version 1.10.7, December 6, 2010, NOT released
+
+ Significant improvements merged from OpenBSD downstream, including:
+ * many new roff(7) components,
+ * in-line implementation of troff's soelim(1),
+ * broken-block handling,
+ * overhauled error classifications, and
+ * cleaned up handling of error conditions.
 
 Changes in version 1.10.6, released on September 27, 2010
 
 
 Changes in version 1.10.6, released on September 27, 2010
 
@@ -194,12 +229,16 @@ Changes in version 1.10.4, released on July 12, 2010
  * Lots of features developed during both "Summer of Code" and the
    OpenBSD c2k10 hackathon:
  * minimal "ds" roff(7) symbols are supported
  * Lots of features developed during both "Summer of Code" and the
    OpenBSD c2k10 hackathon:
  * minimal "ds" roff(7) symbols are supported
- * "Bk" mdoc(7) support
  * beautified SYNOPSIS section output
  * beautified SYNOPSIS section output
- * variable font-width and paper-size support in mandoc(1) -Tps output
  * acceptance of scope-block breakage in mdoc(7)
  * clarify error message status
  * many minor bug-fixes and formatting issues resolved
  * acceptance of scope-block breakage in mdoc(7)
  * clarify error message status
  * many minor bug-fixes and formatting issues resolved
+ * see also changes in 1.10.3
+
+Changes in version 1.10.3, June 29, 2010, NOT released
+
+ * variable font-width and paper-size support in mandoc(1) -Tps output
+ * "Bk" mdoc(7) support
 
 Changes in version 1.10.2, released on June 19, 2010
 
 
 Changes in version 1.10.2, released on June 19, 2010
 
index 0aebbd3..26f42c2 100644 (file)
@@ -1,19 +1,13 @@
 ************************************************************************
 * Official mandoc TODO.
 ************************************************************************
 * Official mandoc TODO.
-* $Id: TODO,v 1.157 2013/09/27 21:12:34 schwarze Exp $
+* $Id: TODO,v 1.162 2013/12/25 14:40:34 schwarze Exp $
 ************************************************************************
 
 ************************************************************************
 * crashes
 ************************************************************************
 
 ************************************************************************
 
 ************************************************************************
 * crashes
 ************************************************************************
 
-- .Bl -tag followed by a text node preceding the first .It should not
-  throw a FATAL error, but only a normal ERROR.  Putting this into the
-  HEAD of an implicit .It might be cleanest, inserting an implicit .Pp
-  or just dumping the orphan stuff directly into the BODY of the .Bl
-  might be easier to implement, and all options can no doubt be made
-  to yield correct (i.e. groff bug-compatible) rendering.
-  Anthony J. Bentley on discuss@  Sun, 22 Sep 2013 16:33:21 -0600
+None known.
 
 ************************************************************************
 * missing features
 
 ************************************************************************
 * missing features
 - .fc (field control)
   found by naddy@ in xloadimage(1)
   
 - .fc (field control)
   found by naddy@ in xloadimage(1)
   
+- .ll (line length)
+  found by naddy@ in textproc/enchant(1)  Sat, 12 Oct 2013 03:27:10 +0200
+
+- .nr third argument (auto-increment step size, requires \n+)
+  found by bentley@ in sbcl(1)  Mon, 9 Dec 2013 18:36:57 -0700
+
 - .ns (no-space mode) occurs in xine-config(1)
   reported by brad@  Sat, 15 Jan 2011 15:45:23 -0500
 
 - .ns (no-space mode) occurs in xine-config(1)
   reported by brad@  Sat, 15 Jan 2011 15:45:23 -0500
 
@@ -67,6 +67,9 @@
   found in cclive(1) DocBook output
   Anthony J. Bentley on discuss@  Sat, 21 Sep 2013 22:29:34 -0600
 
   found in cclive(1) DocBook output
   Anthony J. Bentley on discuss@  Sat, 21 Sep 2013 22:29:34 -0600
 
+- \n+ and \n- numerical register increment and decrement
+  found by bentley@ in sbcl(1)  Mon, 9 Dec 2013 18:36:57 -0700
+
 - using undefined strings or macros defines them to be empty
   wl@  Mon, 14 Nov 2011 14:37:01 +0000
 
 - using undefined strings or macros defines them to be empty
   wl@  Mon, 14 Nov 2011 14:37:01 +0000
 
 
 --- missing misc features ----------------------------------------------
 
 
 --- missing misc features ----------------------------------------------
 
+- italic correction (\/) in PostScript mode
+  Werner LEMBERG on groff at gnu dot org  Sun, 10 Nov 2013 12:47:46
+
 - The whatis(1) utility looks for whole words in Nm.
   If the file name of a page does not agree with the contents of any
   of its Nm macros (e.g. pool(9)), add the file name as an Nm entry
 - The whatis(1) utility looks for whole words in Nm.
   If the file name of a page does not agree with the contents of any
   of its Nm macros (e.g. pool(9)), add the file name as an Nm entry
   noted by stsp@  Sat, 24 Apr 2010 09:17:55 +0200
   reminded by nicm@  Mon, 3 May 2010 09:52:41 +0100
 
   noted by stsp@  Sat, 24 Apr 2010 09:17:55 +0200
   reminded by nicm@  Mon, 3 May 2010 09:52:41 +0100
 
+- look at pages generated from Texinfo source by yat2m, e.g. security/gnupg
+  First impression is not that bad.
+
 - check compatibility with Plan9:
   http://swtch.com/usr/local/plan9/tmac/tmac.an
   http://swtch.com/plan9port/man/man7/man.html
 - check compatibility with Plan9:
   http://swtch.com/usr/local/plan9/tmac/tmac.an
   http://swtch.com/plan9port/man/man7/man.html
 - a column list with blank `Ta' cells triggers a spurrious
   start-with-whitespace printing of a newline
 
 - a column list with blank `Ta' cells triggers a spurrious
   start-with-whitespace printing of a newline
 
-- double quotes inside double quotes are escaped by doubling them
-  implement this in mdoc(7), too
-  so far, we only have it in roff(7) and man(7)
-  reminded by millert@  Thu, 09 Dec 2010 17:29:52 -0500
-
 - In .Bl -column,
   .It Em Authentication<tab>Key Length
   ought to render "Key Length" with emphasis, too,
 - In .Bl -column,
   .It Em Authentication<tab>Key Length
   ought to render "Key Length" with emphasis, too,
   That is, when it is alone on a line between two .Pp,
   we want three blank lines, not two as in mandoc.
 
   That is, when it is alone on a line between two .Pp,
   we want three blank lines, not two as in mandoc.
 
-- When .Fn arguments exceed one output line, all but the first
-  should be indented, see e.g. rpc(3);
-  reported by jmc@ on discuss@  Fri, 29 Oct 2010 13:48:33 +0100
-  reported again by Nicolas Joly via wiz@  Sun, 18 Sep 2011 18:24:40 +0200
-  Also, we don't want to break the line within the argument of:
-  .Fa "chtype tl"
-
 - Header lines of excessive length:
   Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c
   and document it in mdoc(7) and man(7) COMPATIBILITY
 - Header lines of excessive length:
   Port OpenBSD man_term.c rev. 1.25 to mdoc_term.c
   and document it in mdoc(7) and man(7) COMPATIBILITY
index 61002ee..786fc7b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: apropos_db.c,v 1.32.2.1 2013/10/02 21:03:26 schwarze Exp $ */
+/*     $Id: apropos_db.c,v 1.32.2.3 2013/10/10 23:43:04 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 #include <string.h>
 #include <unistd.h>
 
 #include <string.h>
 #include <unistd.h>
 
-#if defined(__linux__)
-# include <endian.h>
-# include <db_185.h>
-#elif defined(__APPLE__)
+#if defined(__APPLE__)
 # include <libkern/OSByteOrder.h>
 # include <libkern/OSByteOrder.h>
-# include <db.h>
+#elif defined(__linux__)
+# include <endian.h>
+#elif defined(__sun)
+# include <sys/byteorder.h>
 #else
 # include <sys/endian.h>
 #else
 # include <sys/endian.h>
+#endif
+
+#if defined(__linux__) || defined(__sun)
+# include <db_185.h>
+#else
 # include <db.h>
 #endif
 
 # include <db.h>
 #endif
 
@@ -414,11 +419,10 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
 {
        struct rectree   tree;
        struct mchars   *mc;
 {
        struct rectree   tree;
        struct mchars   *mc;
-       int              i, rc;
+       int              i;
 
        memset(&tree, 0, sizeof(struct rectree));
 
 
        memset(&tree, 0, sizeof(struct rectree));
 
-       rc = 0;
        mc = mchars_alloc();
        *sz = 0;
        *resp = NULL;
        mc = mchars_alloc();
        *sz = 0;
        *resp = NULL;
index c755d27..8767e5e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: catman.c,v 1.11 2012/06/08 10:33:48 kristaps Exp $ */
+/*     $Id: catman.c,v 1.11.2.2 2013/10/11 00:06:48 schwarze Exp $ */
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <unistd.h>
 
 #include <string.h>
 #include <unistd.h>
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun)
 # include <db_185.h>
 #else
 # include <db.h>
 # include <db_185.h>
 #else
 # include <db.h>
@@ -212,9 +212,6 @@ indexhtml(char *src, size_t ssz, char *dst, size_t dsz)
        const char      *f;
        char            *d;
        char             fname[MAXPATHLEN];
        const char      *f;
        char            *d;
        char             fname[MAXPATHLEN];
-       pid_t            pid;
-
-       pid = -1;
 
        xstrlcpy(fname, dst, MAXPATHLEN);
        xstrlcat(fname, "/", MAXPATHLEN);
 
        xstrlcpy(fname, dst, MAXPATHLEN);
        xstrlcat(fname, "/", MAXPATHLEN);
index 6d40fcd..64bde45 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: cgi.c,v 1.45 2013/06/05 02:00:26 schwarze Exp $ */
+/*     $Id: cgi.c,v 1.46 2013/10/11 00:06:48 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 #include <string.h>
 #include <unistd.h>
 
 #include <string.h>
 #include <unistd.h>
 
+#if defined(__sun)
+/* for stat() */
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
 #include "apropos_db.h"
 #include "mandoc.h"
 #include "mdoc.h"
 #include "apropos_db.h"
 #include "mandoc.h"
 #include "mdoc.h"
@@ -42,7 +49,7 @@
 #include "manpath.h"
 #include "mandocdb.h"
 
 #include "manpath.h"
 #include "mandocdb.h"
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun)
 # include <db_185.h>
 #else
 # include <db.h>
 # include <db_185.h>
 #else
 # include <db.h>
@@ -1097,11 +1104,20 @@ static int
 pathstop(DIR *dir)
 {
        struct dirent   *d;
 pathstop(DIR *dir)
 {
        struct dirent   *d;
+#if defined(__sun)
+       struct stat      sb;
+#endif
 
 
-       while (NULL != (d = readdir(dir)))
+       while (NULL != (d = readdir(dir))) {
+#if defined(__sun)
+               stat(d->d_name, &sb);
+               if (S_IFREG & sb.st_mode)
+#else
                if (DT_REG == d->d_type)
                if (DT_REG == d->d_type)
+#endif
                        if (0 == strcmp(d->d_name, "catman.conf"))
                                return(1);
                        if (0 == strcmp(d->d_name, "catman.conf"))
                                return(1);
+  }
 
        return(0);
 }
 
        return(0);
 }
@@ -1118,6 +1134,9 @@ pathgen(DIR *dir, char *path, struct req *req)
        DIR             *cd;
        int              rc;
        size_t           sz, ssz;
        DIR             *cd;
        int              rc;
        size_t           sz, ssz;
+#if defined(__sun)
+       struct stat      sb;
+#endif
 
        sz = strlcat(path, "/", PATH_MAX);
        if (sz >= PATH_MAX) {
 
        sz = strlcat(path, "/", PATH_MAX);
        if (sz >= PATH_MAX) {
@@ -1133,7 +1152,13 @@ pathgen(DIR *dir, char *path, struct req *req)
 
        rc = 0;
        while (0 == rc && NULL != (d = readdir(dir))) {
 
        rc = 0;
        while (0 == rc && NULL != (d = readdir(dir))) {
-               if (DT_DIR != d->d_type || strcmp(d->d_name, "etc"))
+#if defined(__sun)
+               stat(d->d_name, &sb);
+               if (!(S_IFDIR & sb.st_mode)
+#else
+               if (DT_DIR != d->d_type
+#endif
+        || strcmp(d->d_name, "etc"))
                        continue;
 
                path[(int)sz] = '\0';
                        continue;
 
                path[(int)sz] = '\0';
@@ -1182,7 +1207,13 @@ pathgen(DIR *dir, char *path, struct req *req)
 
        rewinddir(dir);
        while (NULL != (d = readdir(dir))) {
 
        rewinddir(dir);
        while (NULL != (d = readdir(dir))) {
-               if (DT_DIR != d->d_type || '.' == d->d_name[0])
+#if defined(__sun)
+               stat(d->d_name, &sb);
+               if (!(S_IFDIR & sb.st_mode)
+#else
+               if (DT_DIR != d->d_type
+#endif
+        || '.' == d->d_name[0])
                        continue;
 
                path[(int)sz] = '\0';
                        continue;
 
                path[(int)sz] = '\0';
index cee82aa..9a33671 100644 (file)
@@ -19,6 +19,9 @@
 #  if defined(__APPLE__)
 #    define betoh64(x) OSSwapBigToHostInt64(x)
 #    define htobe64(x) OSSwapHostToBigInt64(x)
 #  if defined(__APPLE__)
 #    define betoh64(x) OSSwapBigToHostInt64(x)
 #    define htobe64(x) OSSwapHostToBigInt64(x)
+#  elif defined(__sun)
+#    define betoh64(x) BE_64(x)
+#    define htobe64(x) BE_64(x)
 #  else
 #    define betoh64(x) be64toh(x)
 #  endif
 #  else
 #    define betoh64(x) be64toh(x)
 #  endif
index e716635..83a43a7 100644 (file)
@@ -7,6 +7,7 @@
        </HEAD>
        <BODY>
                <P CLASS="head">
        </HEAD>
        <BODY>
                <P CLASS="head">
+                       <A HREF="http://www.openbsd.org/"><IMG SRC="puffy.gif" ALT="Puffy" WIDTH="100" HEIGHT="91" STYLE="float: right"></A>
                        <B>mdocml</B> &#8211; UNIX manpage compiler, current version @VERSION@ (@VDATE@)
                </P>
                <P CLASS="subhead">
                        <B>mdocml</B> &#8211; UNIX manpage compiler, current version @VERSION@ (@VDATE@)
                </P>
                <P CLASS="subhead">
                <P>
                        <SPAN CLASS="nm">mdocml</SPAN> is a suite of tools compiling <I><A HREF="mdoc.7.html">mdoc</A></I>, the roff macro
                        package of choice for BSD manual pages, and <I><A HREF="man.7.html">man</A></I>, the predominant historical package for
                <P>
                        <SPAN CLASS="nm">mdocml</SPAN> is a suite of tools compiling <I><A HREF="mdoc.7.html">mdoc</A></I>, the roff macro
                        package of choice for BSD manual pages, and <I><A HREF="man.7.html">man</A></I>, the predominant historical package for
-                       UNIX manuals.  The mission of <SPAN CLASS="nm">mdocml</SPAN> is to deprecate <A
-                       HREF="http://www.gnu.org/software/groff/" CLASS="external">groff</A>, the GNU troff implementation, for displaying <I>mdoc</I>
-                       pages whilst providing token support for <I>man</I>.
+                       UNIX manuals.
+                       It is small, ISO C, <A CLASS="external" HREF="http://www.isc.org/software/license">ISC</A>-licensed, and quite fast.
                </P>
                <P>
                </P>
                <P>
-                       Why?  groff amounts to over 5 MB of source code, most of which is C++ and GPL version 3.  It runs slowly, produces
-                       uncertain output, and varies in operation from system to system.  mdocml strives to fix this (respectively small, C, <A
-                       CLASS="external" HREF="http://www.isc.org/software/license">ISC</A>-licensed, fast and regular).
-               </P>
-               <P>
-                       <SPAN CLASS="nm">mdocml</SPAN> consists of the <A HREF="mandoc.3.html">libmandoc</A> validating compiler and <A
-                       HREF="mandoc.1.html">mandoc</A>, which interfaces with the compiler library to format output for UNIX terminals (with
+                       The tool set features <A HREF="mandoc.1.html">mandoc</A>,
+                       based on the <A HREF="mandoc.3.html">libmandoc</A> validating compiler,
+                       to format output for UNIX terminals (with
                        support for wide-character locales), XHTML, HTML, PostScript, and PDF.  
                        It also includes <A HREF="preconv.1.html">preconv</A>, for recoding multibyte manuals; 
                        <A HREF="demandoc.1.html">demandoc</A>, for emitting only text parts of manuals;
                        <A HREF="mandocdb.8.html">mandocdb</A>, for indexing manuals; and
                        <A HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, and
                        <A HREF="man.cgi.7.html">man.cgi</A> (via <A HREF="catman.8.html">catman</A>) for semantic search of manual content.
                        support for wide-character locales), XHTML, HTML, PostScript, and PDF.  
                        It also includes <A HREF="preconv.1.html">preconv</A>, for recoding multibyte manuals; 
                        <A HREF="demandoc.1.html">demandoc</A>, for emitting only text parts of manuals;
                        <A HREF="mandocdb.8.html">mandocdb</A>, for indexing manuals; and
                        <A HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, and
                        <A HREF="man.cgi.7.html">man.cgi</A> (via <A HREF="catman.8.html">catman</A>) for semantic search of manual content.
-                       It is a <A CLASS="external" HREF="http://bsd.lv/">BSD.lv</A> project.  
+               </P>
+               <P>
+                       <SPAN CLASS="nm">mdocml</SPAN> has predominantly been developed on OpenBSD
+                       and is both an <A CLASS="external" HREF="http://www.openbsd.org/">OpenBSD</A>
+                       and a <A CLASS="external" HREF="http://bsd.lv/">BSD.lv</A> project.  
+                       We strive to support all interested free operating systems, in particular
+                       <A CLASS="external" HREF="http://www.dragonflybsd.org/">DragonFly</A>,
+                       <A CLASS="external" HREF="http://www.netbsd.org/">NetBSD</A>,
+                       <A CLASS="external" HREF="http://www.freebsd.org/">FreeBSD</A>,
+                       <A CLASS="external" HREF="http://www.minix3.org/">Minix 3</A>,
+                       and <A CLASS="external" HREF="http://www.gnu.org/">GNU</A>/Linux,
+                       as well as all systems running the <A CLASS="external" HREF="http://www.pkgsrc.org/">pkgsrc</A> portable package build system.
+                       All of these projects have helped to make <SPAN CLASS="nm">mdocml</SPAN> better, by providing feedback and advice,
+                       bug reports, and patches.
                </P>
                <P>
                        <I>Disambiguation</I>: <SPAN CLASS="nm">mdocml</SPAN> is often referred to by its installed binary, <Q>mandoc</Q>.
                </P>
                <P>
                        <I>Disambiguation</I>: <SPAN CLASS="nm">mdocml</SPAN> is often referred to by its installed binary, <Q>mandoc</Q>.
                        <A NAME="sources">Sources</A>
                </H2>
                <P>
                        <A NAME="sources">Sources</A>
                </H2>
                <P>
-                       <SPAN CLASS="nm">mdocml</SPAN> is in plain-old ANSI C and should build and run on any modern system; however, you'll
-                       need <A HREF="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">libdb</A> to build <A
-                       HREF="apropos.1.html">apropos</A>, <A HREF="whatis.1.html">whatis</A>, <A HREF="man.cgi.7.html">man.cgi</A>, <A
-                       HREF="catman.8.html">catman</A>, and <A HREF="mandocdb.8.html">mandocdb</A> (this is installed by default on BSD UNIX
-                       systems &mdash; see the <I>Makefile</I> if you're running Linux).  To build and install into <I>/usr/local/</I>, just
-                       run <CODE>make install</CODE>.  Be careful: the <B>preconv</B>, <B>apropos</B>, and <B>whatis</B> binary names are
-                       usually taken by existing utilities.
+                       <SPAN CLASS="nm">mdocml</SPAN> should build and run on any modern system with
+                       <A HREF="http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html">libdb</A>
+                       (this is installed by default on BSD UNIX systems &mdash; see the <I>Makefile</I> if you're running Linux).
+                       To build and install into <I>/usr/local/</I>, just run <CODE>make install</CODE>.
+                       Be careful: the <B>preconv</B>, <B>apropos</B>, and <B>whatis</B> installed binary names
+                       may be taken by existing utilities.
                </P>
                <H2>
                        Downstream
                </P>
                <H2>
                        Downstream
@@ -61,8 +69,7 @@
                <P>
                        Several systems come bundled with <SPAN CLASS="nm">mdocml</SPAN> utilities.
                        If your system does not appear below, the maintainers have not contacted me and it should not be considered
                <P>
                        Several systems come bundled with <SPAN CLASS="nm">mdocml</SPAN> utilities.
                        If your system does not appear below, the maintainers have not contacted me and it should not be considered
-                       <Q>official</Q>.
-                       Please <A HREF="#contact">contact us</A> if you plan on maintaining a downstream version!
+                       <Q>official</Q>, so please <A HREF="#contact">contact us</A> if you plan on maintaining a downstream version!
                </P>
                <TABLE WIDTH="100%" SUMMARY="Downstream Sources">
                        <COL WIDTH="175">
                </P>
                <TABLE WIDTH="100%" SUMMARY="Downstream Sources">
                        <COL WIDTH="175">
@@ -71,7 +78,7 @@
                                <TR>
                                        <TD>DragonFly BSD</TD>
                                        <TD>
                                <TR>
                                        <TD>DragonFly BSD</TD>
                                        <TD>
-                                       <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/contrib/mdocml" CLASS="external">contrib/mdocml</A> (1.12.1 sources)
+                                       <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/contrib/mdocml" CLASS="external">contrib/mdocml</A> (1.12.3 sources)
                                        <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/lib/libmandoc" CLASS="external">lib/libmandoc</A>
                                        <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/usr.bin/mandoc" CLASS="external">usr.bin/mandoc</A> (build system)
                                        </TD>
                                        <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/lib/libmandoc" CLASS="external">lib/libmandoc</A>
                                        <A HREF="http://gitweb.dragonflybsd.org/dragonfly.git/tree/HEAD:/usr.bin/mandoc" CLASS="external">usr.bin/mandoc</A> (build system)
                                        </TD>
@@ -86,7 +93,7 @@
                                <TR>
                                        <TD>FreeBSD 9.x, 8.x</TD>
                                        <TD>
                                <TR>
                                        <TD>FreeBSD 9.x, 8.x</TD>
                                        <TD>
-                                       <A HREF="http://svnweb.freebsd.org/ports/textproc/mdocml/" CLASS="external">ports/textproc/mdocml</A> (1.12.1 port)
+                                       <A HREF="http://svnweb.freebsd.org/ports/head/textproc/mdocml/" CLASS="external">ports/textproc/mdocml</A> (1.12.2 port)
                                        </TD>
                                </TR>
                                <TR>
                                        </TD>
                                </TR>
                                <TR>
                                <TR>
                                        <TD>OpenBSD</TD>
                                        <TD>
                                <TR>
                                        <TD>OpenBSD</TD>
                                        <TD>
-                                       <A HREF="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/mandoc/" CLASS="external">src/usr.bin/mandoc</A> (1.12.2 sources and build system)
+                                       <A HREF="http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/mandoc/" CLASS="external">src/usr.bin/mandoc</A> (1.12.3 sources under active development and build system)
                                        </TD>
                                </TR>
                                <TR>
                                        <TD>pkgsrc</TD>
                                        <TD>
                                        </TD>
                                </TR>
                                <TR>
                                        <TD>pkgsrc</TD>
                                        <TD>
-                                       <A HREF="http://pkgsrc.se/textproc/mdocml" CLASS="external">textproc/mdocml</A> (1.12.0 port)
+                                       <A HREF="http://pkgsrc.se/textproc/mdocml" CLASS="external">textproc/mdocml</A> (1.12.2 port)
                                        </TD>
                                </TR>
                                <TR>
                                        </TD>
                                </TR>
                                <TR>
                                <TR>
                                        <TD>Alpine Linux</TD>
                                        <TD>
                                <TR>
                                        <TD>Alpine Linux</TD>
                                        <TD>
-                                       <A HREF="http://git.alpinelinux.org/cgit/aports/tree/main/mdocml" CLASS="external">aports/main/mdocml</A> (1.12.1 port)
+                                       <A HREF="http://git.alpinelinux.org/cgit/aports/tree/main/mdocml" CLASS="external">aports/main/mdocml</A> (1.12.2 port)
                                        </TD>
                                </TR>
                        </TBODY>
                                        </TD>
                                </TR>
                        </TBODY>
                                </TR>
                        </TBODY>
                </TABLE>
                                </TR>
                        </TBODY>
                </TABLE>
+               <H2>
+                       <A NAME="links">Supplementary Information</A>
+               </H2>
+               <UL>
+                       <LI>
+                               <A HREF="http://manpages.bsd.lv/">Practical UNIX Manuals</A>: mdoc tutorial by Kristaps Dzonsons
+                       </LI>
+                       <LI>
+                               <A HREF="http://www.openbsd.org/faq/ports/specialtopics.html#Mandoc" CLASS="external">OpenBSD porting guide</A>
+                               chapter regarding manual pages
+                       </LI>
+                       <LI>
+                               <A HREF="press.html">Publications and media coverage</A>
+                               concerning mdocml and mandoc
+                       </LI>
+                       <LI>
+                               <A HREF="http://manpages.bsd.lv/history.html">History of UNIX Manpages</A>: a comprehensive overview by Kristaps Dzonsons
+                       </LI>
+               </UL>
                <H1>
                        <A NAME="contact">Contact</A>
                </H1>
                <H1>
                        <A NAME="contact">Contact</A>
                </H1>
                        <A NAME="news">News</A>
                </H1>
                <P CLASS="news">
                        <A NAME="news">News</A>
                </H1>
                <P CLASS="news">
-                       02-10-2013: version 1.12.2
+                       31-12-2013: version 1.12.3
+               </P>
+               <P>
+                       In the <A HREF="mdoc.7.html">mdoc(7)</A> SYNOPSIS, line breaks and hanging indentation
+                       now work correctly for .Fo/.Fa/.Fc and .Fn blocks.
+                       Thanks to Franco Fichtner for doing part of the work.
+               </P>
+               <P>
+                       The <A HREF="mdoc.7.html">mdoc(7)</A> .Bk macro got some addititonal bugfixes.
+               </P>
+               <P>
+                       In <A HREF="mdoc.7.html">mdoc(7)</A> macro arguments, double quotes can now be quoted 
+                       by doubling them, just like in <A HREF="man.7.html">man(7)</A>.  
+                       Thanks to Tsugutomo ENAMI for the patch.
+               </P>
+               <P>
+                       At the end of <A HREF="man.7.html">man(7)</A> macro lines, end-of-sentence spacing
+                       now works.  Thanks to Franco Fichtner for the patch.
+               </P>
+               <P>
+                       For backward compatibility, the <A HREF="man.7.html">man(7)</A> parser now supports the
+                       man-ext .UR/.UE (uniform resource identifier) block macros.
+               </P>
+               <P>
+                       The <A HREF="man.7.html">man(7)</A> parser now handles closing blocks that are not open
+                       more gracefully.
+               </P>
+               <P>
+                       The <A HREF="man.7.html">man(7)</A> parser now ignores blank lines right after .SH and .SS.
+               </P>
+               <P>
+                       In the <A HREF="man.7.html">man(7)</A> formatter, reset indentation when leaving a block,
+                       not just when entering the next one.
+               </P>
+               <P>
+                       The <A HREF="roff.7.html">roff(7)</A> .nr request now supports incrementing and decrementing
+                       number registers and stops parsing the number right before the first non-digit character.
+               </P>
+               <P>
+                       The <A HREF="roff.7.html">roff(7)</A> parser now supports the alternative escape sequence
+                       syntax \C'uXXXX' for Unicode characters.
+               </P>
+               <P>
+                       The <A HREF="roff.7.html">roff(7)</A> parser now parses and ignores the .fam (font family) 
+                       and .hw (hyphenation points) requests and the \d and \u escape sequences.                  
+               </P>
+               <P>
+                       The <A HREF="roff.7.html">roff(7)</A> manual got a new ESCAPE SEQUENCE REFERENCE.
+               </P>
+               <P CLASS="news">
+                       05-10-2013: version 1.12.2
                </P>
                <P>
                        The <A HREF="mdoc.7.html">mdoc(7)</A> to <A HREF="man.7.html">man(7)</A> converter,
                </P>
                <P>
                        The <A HREF="mdoc.7.html">mdoc(7)</A> to <A HREF="man.7.html">man(7)</A> converter,
                        For mandoc developers, we now provide a <A HREF="tbl.3.html">tbl(3)</A> library manual and <CODE>gmdiff</CODE>,
                        a very small, very simplistic groff-versus-mandoc output comparison tool.
                </P>
                        For mandoc developers, we now provide a <A HREF="tbl.3.html">tbl(3)</A> library manual and <CODE>gmdiff</CODE>,
                        a very small, very simplistic groff-versus-mandoc output comparison tool.
                </P>
-               <P>
-                       See <A HREF="NEWS">NEWS</A> for historical notes.
-               </P>
-               <P CLASS="news">
-                       23-03-2011: version 1.12.1
-               </P>
-               <P>
-                       Significant work on <A HREF="apropos.1.html">apropos</A> and <A HREF="mandocdb.8.html">mandocdb</A>.  These tools are
-                       now much more robust.  
-                       A <A HREF="whatis.1.html">whatis</A> implementation is now handled as an <A HREF="apropos.1.html">apropos</A> mode.
-                       These tools are also able to minimally handle pre-formatted pages, that is, those already formatted by another utility
-                       such as GNU troff.
-               </P>
-               <P>
-                       The <A HREF="man.cgi.7.html">man.cgi</A> script is also now available for wider testing.  It interfaces with <A
-                       HREF="mandocdb.8.html">mandocdb</A> manuals cached by <A HREF="catman.8.html">catman</A>.  HTML output is generated
-                       on-the-fly by <A HREF="mandoc.3.html">libmandoc</A> or internal methods to convert pre-formatted pages.
-               </P>
-               <P>
-                       The mailing list archive for the discuss and tech lists are being hosted by <A CLASS="external"
-                       HREF="http://www.gmane.org">Gmane</A> at <A HREF="http://dir.gmane.org/gmane.comp.tools.mdocml.user"
-                       CLASS="external">gmane.comp.tools.mdocml.user</A> and <A HREF="http://dir.gmane.org/gmane.comp.tools.mdocml.devel"
-                       CLASS="external">gmane.comp.tools.mdocml.devel</A>, respectively.
-               </P>
-               <P>
-                       Lastly, I'm no longer providing binaries, as nobody has asked for them.
-               </P>
-               <P>
-                       See <A HREF="http://mdocml.bsd.lv/cgi-bin/cvsweb/index.sgml?cvsroot=mdocml">cvsweb</A> for
-                       historical notes.
-               </P>
+               <H2>
+                       <A>History</A>
+               </H2>
+               <UL>
+                       <LI>
+                               <A HREF="NEWS">Release notes</A> going back to release 1.9.15, February 18, 2010.
+                               Briefly explaining the most important changes in each release in relatively easy terms.
+                               Very many changes are not mentioned here.
+                       </LI>
+                       <LI>
+                               <A HREF="history.html">Development history</A> going back to the beginning of the project, November 22, 2008.
+                               One-line entries for important commits, releases, merges, hackathons and talks.
+                               Makes it easy to find out who did what, and when, and when it became available where.
+                               However, this is still incomplete, mentioning only a small fraction of all commits,
+                               and to keep the size down, the individual entries are extremely terse and technical.
+                               Feel free to look up more details and longer explanations about individual entries
+                               in the ChangeLog or in CVS.
+                       </LI>
+                       <LI>
+                               <A HREF="ChangeLog">CVS ChangeLog</A> going back to the beginning of the project.
+                               Very technical information of varying quality, strictly chronological.
+                               All commits are mentioned, but some messages neglect to mention some changes.
+                               Partly terse, partly detailed and verbose.  In any case, the ChangeLog is very long -
+                               more than 25,000 lines, more than 700 kB.
+                       </LI>
+                       <LI>
+                               <A HREF="/cgi-bin/cvsweb/?cvsroot=mdocml">CVS</A> web interface, going back to the beginning of the project.
+                               Source code, diffs and commit messages for each source file.  The real thing.
+                       </LI>
+               </UL>
                <P CLASS="foot">
                        <SMALL>
                                Copyright &#169; 2008&#8211;2011 
                                <A CLASS="external" HREF="http://kristaps.bsd.lv">Kristaps Dzonsons</A>, 
                                &#169; 2013 Ingo Schwarze,
                <P CLASS="foot">
                        <SMALL>
                                Copyright &#169; 2008&#8211;2011 
                                <A CLASS="external" HREF="http://kristaps.bsd.lv">Kristaps Dzonsons</A>, 
                                &#169; 2013 Ingo Schwarze,
-                               $Date: 2013/10/05 14:05:09 $
+                               $Date: 2013/12/31 $
                        </SMALL>
                </P>
        </BODY>
                        </SMALL>
                </P>
        </BODY>
index 230a465..334e093 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: lib.in,v 1.13 2012/01/28 23:46:28 joerg Exp $ */
+/*     $Id: lib.in,v 1.17 2013/10/13 15:24:03 schwarze Exp $ */
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Be sure to escape strings.
  */
 
  * Be sure to escape strings.
  */
 
-LINE("libarchive",     "Reading and Writing Streaming Archives Library (libarchive, \\-larchive)")
+LINE("libalias",       "Packet Aliasing Library (libalias, \\-lalias)")
+LINE("libarchive",     "Streaming Archive Library (libarchive, \\-larchive)")
 LINE("libarm",         "ARM Architecture Library (libarm, \\-larm)")
 LINE("libarm32",       "ARM32 Architecture Library (libarm32, \\-larm32)")
 LINE("libbluetooth",   "Bluetooth Library (libbluetooth, \\-lbluetooth)")
 LINE("libarm",         "ARM Architecture Library (libarm, \\-larm)")
 LINE("libarm32",       "ARM32 Architecture Library (libarm32, \\-larm32)")
 LINE("libbluetooth",   "Bluetooth Library (libbluetooth, \\-lbluetooth)")
+LINE("libbsdxml",      "eXpat XML parser library (libbsdxml, \\-lbsdxml)")
 LINE("libbsm",         "Basic Security Module User Library (libbsm, \\-lbsm)")
 LINE("libc",           "Standard C Library (libc, \\-lc)")
 LINE("libc_r",         "Reentrant C\\~Library (libc_r, \\-lc_r)")
 LINE("libbsm",         "Basic Security Module User Library (libbsm, \\-lbsm)")
 LINE("libc",           "Standard C Library (libc, \\-lc)")
 LINE("libc_r",         "Reentrant C\\~Library (libc_r, \\-lc_r)")
@@ -37,17 +39,24 @@ LINE("libcipher",   "FreeSec Crypt Library (libcipher, \\-lcipher)")
 LINE("libcompat",      "Compatibility Library (libcompat, \\-lcompat)")
 LINE("libcrypt",       "Crypt Library (libcrypt, \\-lcrypt)")
 LINE("libcurses",      "Curses Library (libcurses, \\-lcurses)")
 LINE("libcompat",      "Compatibility Library (libcompat, \\-lcompat)")
 LINE("libcrypt",       "Crypt Library (libcrypt, \\-lcrypt)")
 LINE("libcurses",      "Curses Library (libcurses, \\-lcurses)")
+LINE("libdevattr",     "Device attribute and event library (libdevattr, \\-ldevattr)")
 LINE("libdevinfo",     "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
 LINE("libdevstat",     "Device Statistics Library (libdevstat, \\-ldevstat)")
 LINE("libdisk",                "Interface to Slice and Partition Labels Library (libdisk, \\-ldisk)")
 LINE("libdevinfo",     "Device and Resource Information Utility Library (libdevinfo, \\-ldevinfo)")
 LINE("libdevstat",     "Device Statistics Library (libdevstat, \\-ldevstat)")
 LINE("libdisk",                "Interface to Slice and Partition Labels Library (libdisk, \\-ldisk)")
+LINE("libdm",          "Device Mapper Library (libdm, \\-ldm)")
 LINE("libdwarf",       "DWARF Access Library (libdwarf, \\-ldwarf)")
 LINE("libedit",                "Command Line Editor Library (libedit, \\-ledit)")
 LINE("libdwarf",       "DWARF Access Library (libdwarf, \\-ldwarf)")
 LINE("libedit",                "Command Line Editor Library (libedit, \\-ledit)")
+LINE("libefi",         "EFI Runtime Services Library (libefi, \\-lefi)")
 LINE("libelf",         "ELF Access Library (libelf, \\-lelf)")
 LINE("libevent",       "Event Notification Library (libevent, \\-levent)")
 LINE("libelf",         "ELF Access Library (libelf, \\-lelf)")
 LINE("libevent",       "Event Notification Library (libevent, \\-levent)")
-LINE("libfetch",       "File Transfer Library for URLs (libfetch, \\-lfetch)")
+LINE("libexecinfo",    "Backtrace Information Library (libexecinfo, \\-lexecinfo)")
+LINE("libfetch",       "File Transfer Library (libfetch, \\-lfetch)")
+LINE("libfsid",                "Filesystem Identification Library (libfsid, \\-lfsid)")
+LINE("libftpio",       "FTP Connection Management Library (libftpio, \\-lftpio)")
 LINE("libform",                "Curses Form Library (libform, \\-lform)")
 LINE("libform",                "Curses Form Library (libform, \\-lform)")
-LINE("libgeom",                "Userland API Library for kernel GEOM subsystem (libgeom, \\-lgeom)")
+LINE("libgeom",                "Userland API Library for Kernel GEOM subsystem (libgeom, \\-lgeom)")
 LINE("libgpib",                "General-Purpose Instrument Bus (GPIB) library (libgpib, \\-lgpib)")
 LINE("libgpib",                "General-Purpose Instrument Bus (GPIB) library (libgpib, \\-lgpib)")
+LINE("libhammer",      "HAMMER Filesystem Userland Library (libhammer, \\-lhammer)")
 LINE("libi386",                "i386 Architecture Library (libi386, \\-li386)")
 LINE("libintl",                "Internationalized Message Handling Library (libintl, \\-lintl)")
 LINE("libipsec",       "IPsec Policy Control Library (libipsec, \\-lipsec)")
 LINE("libi386",                "i386 Architecture Library (libi386, \\-li386)")
 LINE("libintl",                "Internationalized Message Handling Library (libintl, \\-lintl)")
 LINE("libipsec",       "IPsec Policy Control Library (libipsec, \\-lipsec)")
@@ -55,37 +64,49 @@ LINE("libipx",              "IPX Address Conversion Support Library (libipx, \\-lipx)")
 LINE("libiscsi",       "iSCSI protocol library (libiscsi, \\-liscsi)")
 LINE("libisns",                "Internet Storage Name Service Library (libisns, \\-lisns)")
 LINE("libjail",                "Jail Library (libjail, \\-ljail)")
 LINE("libiscsi",       "iSCSI protocol library (libiscsi, \\-liscsi)")
 LINE("libisns",                "Internet Storage Name Service Library (libisns, \\-lisns)")
 LINE("libjail",                "Jail Library (libjail, \\-ljail)")
-LINE("libkiconv",      "Kernel side iconv library (libkiconv, \\-lkiconv)")
+LINE("libkcore",       "Kernel Memory Core Access Library (libkcore, \\-lkcore)")
+LINE("libkiconv",      "Kernel-side iconv Library (libkiconv, \\-lkiconv)")
 LINE("libkse",         "N:M Threading Library (libkse, \\-lkse)")
 LINE("libkvm",         "Kernel Data Access Library (libkvm, \\-lkvm)")
 LINE("libm",           "Math Library (libm, \\-lm)")
 LINE("libm68k",                "m68k Architecture Library (libm68k, \\-lm68k)")
 LINE("libmagic",       "Magic Number Recognition Library (libmagic, \\-lmagic)")
 LINE("libkse",         "N:M Threading Library (libkse, \\-lkse)")
 LINE("libkvm",         "Kernel Data Access Library (libkvm, \\-lkvm)")
 LINE("libm",           "Math Library (libm, \\-lm)")
 LINE("libm68k",                "m68k Architecture Library (libm68k, \\-lm68k)")
 LINE("libmagic",       "Magic Number Recognition Library (libmagic, \\-lmagic)")
+LINE("libmandoc",      "Mandoc Macro Compiler Library (libmandoc, \\-lmandoc)")
 LINE("libmd",          "Message Digest (MD4, MD5, etc.) Support Library (libmd, \\-lmd)")
 LINE("libmemstat",     "Kernel Memory Allocator Statistics Library (libmemstat, \\-lmemstat)")
 LINE("libmenu",                "Curses Menu Library (libmenu, \\-lmenu)")
 LINE("libmd",          "Message Digest (MD4, MD5, etc.) Support Library (libmd, \\-lmd)")
 LINE("libmemstat",     "Kernel Memory Allocator Statistics Library (libmemstat, \\-lmemstat)")
 LINE("libmenu",                "Curses Menu Library (libmenu, \\-lmenu)")
+LINE("libmj",          "Minimalist JSON library (libmj, \\-lmj)")
 LINE("libnetgraph",    "Netgraph User Library (libnetgraph, \\-lnetgraph)")
 LINE("libnetgraph",    "Netgraph User Library (libnetgraph, \\-lnetgraph)")
-LINE("libnetpgp",      "Netpgp signing, verification, encryption and decryption (libnetpgp, \\-lnetpgp)")
+LINE("libnetpgp",      "Netpgp Signing, Verification, Encryption and Decryption (libnetpgp, \\-lnetpgp)")
+LINE("libnetpgpverify",        "Netpgp Verification (libnetpgpverify, \\-lnetpgpverify)")
+LINE("libnpf",         "NPF Packet Filter Library (libnpf, \\-lnpf)")
 LINE("libossaudio",    "OSS Audio Emulation Library (libossaudio, \\-lossaudio)")
 LINE("libpam",         "Pluggable Authentication Module Library (libpam, \\-lpam)")
 LINE("libpcap",                "Capture Library (libpcap, \\-lpcap)")
 LINE("libpci",         "PCI Bus Access Library (libpci, \\-lpci)")
 LINE("libpmc",         "Performance Counters Library (libpmc, \\-lpmc)")
 LINE("libossaudio",    "OSS Audio Emulation Library (libossaudio, \\-lossaudio)")
 LINE("libpam",         "Pluggable Authentication Module Library (libpam, \\-lpam)")
 LINE("libpcap",                "Capture Library (libpcap, \\-lpcap)")
 LINE("libpci",         "PCI Bus Access Library (libpci, \\-lpci)")
 LINE("libpmc",         "Performance Counters Library (libpmc, \\-lpmc)")
+LINE("libppath",       "Property-List Paths Library (libppath, \\-lppath)")
 LINE("libposix",       "POSIX Compatibility Library (libposix, \\-lposix)")
 LINE("libposix",       "POSIX Compatibility Library (libposix, \\-lposix)")
+LINE("libposix1e",     "POSIX.1e Security API Library (libposix1e, \\-lposix1e)")
 LINE("libppath",       "Property-List Paths Library (libppath, \\-lppath)")
 LINE("libprop",                "Property Container Object Library (libprop, \\-lprop)")
 LINE("libpthread",     "POSIX Threads Library (libpthread, \\-lpthread)")
 LINE("libpuffs",       "puffs Convenience Library (libpuffs, \\-lpuffs)")
 LINE("libquota",       "Disk Quota Access and Control Library (libquota, \\-lquota)")
 LINE("libppath",       "Property-List Paths Library (libppath, \\-lppath)")
 LINE("libprop",                "Property Container Object Library (libprop, \\-lprop)")
 LINE("libpthread",     "POSIX Threads Library (libpthread, \\-lpthread)")
 LINE("libpuffs",       "puffs Convenience Library (libpuffs, \\-lpuffs)")
 LINE("libquota",       "Disk Quota Access and Control Library (libquota, \\-lquota)")
+LINE("libradius",      "RADIUS Client Library (libradius, \\-lradius)")
 LINE("librefuse",      "File System in Userspace Convenience Library (librefuse, \\-lrefuse)")
 LINE("libresolv",      "DNS Resolver Library (libresolv, \\-lresolv)")
 LINE("librpcsec_gss",  "RPC GSS-API Authentication Library (librpcsec_gss, \\-lrpcsec_gss)")
 LINE("librpcsvc",      "RPC Service Library (librpcsvc, \\-lrpcsvc)")
 LINE("librt",          "POSIX Real\\-time Library (librt, \\-lrt)")
 LINE("librefuse",      "File System in Userspace Convenience Library (librefuse, \\-lrefuse)")
 LINE("libresolv",      "DNS Resolver Library (libresolv, \\-lresolv)")
 LINE("librpcsec_gss",  "RPC GSS-API Authentication Library (librpcsec_gss, \\-lrpcsec_gss)")
 LINE("librpcsvc",      "RPC Service Library (librpcsvc, \\-lrpcsvc)")
 LINE("librt",          "POSIX Real\\-time Library (librt, \\-lrt)")
+LINE("librumpclient",  "Clientside Stubs for rump Kernel Remote Protocols (librumpclient, \\-lrumpclient)")
 LINE("libsaslc",       "Simple Authentication and Security Layer client library (libsaslc, \\-lsaslc)")
 LINE("libsdp",         "Bluetooth Service Discovery Protocol User Library (libsdp, \\-lsdp)")
 LINE("libssp",         "Buffer Overflow Protection Library (libssp, \\-lssp)")
 LINE("libsaslc",       "Simple Authentication and Security Layer client library (libsaslc, \\-lsaslc)")
 LINE("libsdp",         "Bluetooth Service Discovery Protocol User Library (libsdp, \\-lsdp)")
 LINE("libssp",         "Buffer Overflow Protection Library (libssp, \\-lssp)")
+LINE("libstand",       "Standalone Applications Library (libstand, \\-lstand)")
 LINE("libSystem",      "System Library (libSystem, \\-lSystem)")
 LINE("libSystem",      "System Library (libSystem, \\-lSystem)")
+LINE("libtacplus",     "TACACS+ Client Library (libtacplus, \\-ltacplus)")
+LINE("libtcplay",      "TrueCrypt-compatible API library (libtcplay, \\-ltcplay)")
 LINE("libtermcap",     "Termcap Access Library (libtermcap, \\-ltermcap)")
 LINE("libterminfo",    "Terminal Information Library (libterminfo, \\-lterminfo)")
 LINE("libthr",         "1:1 Threading Library (libthr, \\-lthr)")
 LINE("libtermcap",     "Termcap Access Library (libtermcap, \\-ltermcap)")
 LINE("libterminfo",    "Terminal Information Library (libterminfo, \\-lterminfo)")
 LINE("libthr",         "1:1 Threading Library (libthr, \\-lthr)")
index 9b3ffee..3c005e1 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: libmandoc.h,v 1.32 2012/11/19 17:57:23 schwarze Exp $ */
+/*     $Id: libmandoc.h,v 1.35 2013/12/15 21:23:52 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -29,11 +30,6 @@ enum rofferr {
        ROFF_ERR /* badness: puke and stop */
 };
 
        ROFF_ERR /* badness: puke and stop */
 };
 
-enum   regs {
-       REG_nS = 0, /* nS register */
-       REG__MAX
-};
-
 __BEGIN_DECLS
 
 struct roff;
 __BEGIN_DECLS
 
 struct roff;
@@ -72,9 +68,8 @@ void           roff_reset(struct roff *);
 enum rofferr    roff_parseln(struct roff *, int, 
                        char **, size_t *, int, int *);
 void            roff_endparse(struct roff *);
 enum rofferr    roff_parseln(struct roff *, int, 
                        char **, size_t *, int, int *);
 void            roff_endparse(struct roff *);
-int             roff_regisset(const struct roff *, enum regs);
-unsigned int    roff_regget(const struct roff *, enum regs);
-void            roff_regunset(struct roff *, enum regs);
+void            roff_setreg(struct roff *, const char *, int, char sign);
+int             roff_getreg(const struct roff *, const char *);
 char           *roff_strdup(const struct roff *, const char *);
 int             roff_getcontrol(const struct roff *, 
                        const char *, int *);
 char           *roff_strdup(const struct roff *, const char *);
 int             roff_getcontrol(const struct roff *, 
                        const char *, int *);
index 8a389a4..3f14519 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: libmdoc.h,v 1.81 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: libmdoc.h,v 1.82 2013/10/21 23:47:58 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -34,6 +35,8 @@ struct        mdoc {
 #define        MDOC_PPHRASE     (1 << 5) /* within a partial phrase */
 #define        MDOC_FREECOL     (1 << 6) /* `It' invocation should close */
 #define        MDOC_SYNOPSIS    (1 << 7) /* SYNOPSIS-style formatting */
 #define        MDOC_PPHRASE     (1 << 5) /* within a partial phrase */
 #define        MDOC_FREECOL     (1 << 6) /* `It' invocation should close */
 #define        MDOC_SYNOPSIS    (1 << 7) /* SYNOPSIS-style formatting */
+#define        MDOC_KEEP        (1 << 8) /* in a word keep */
+#define        MDOC_SMOFF       (1 << 9) /* spacing is off */
        enum mdoc_next    next; /* where to put the next node */
        struct mdoc_node *last; /* the last node parsed */
        struct mdoc_node *first; /* the first node parsed */
        enum mdoc_next    next; /* where to put the next node */
        struct mdoc_node *last; /* the last node parsed */
        struct mdoc_node *first; /* the first node parsed */
@@ -57,8 +60,8 @@ struct        mdoc_macro {
 #define        MDOC_PARSED      (1 << 1)
 #define        MDOC_EXPLICIT    (1 << 2)
 #define        MDOC_PROLOGUE    (1 << 3)
 #define        MDOC_PARSED      (1 << 1)
 #define        MDOC_EXPLICIT    (1 << 2)
 #define        MDOC_PROLOGUE    (1 << 3)
-#define        MDOC_IGNDELIM    (1 << 4) 
-       /* Reserved words in arguments treated as text. */
+#define        MDOC_IGNDELIM    (1 << 4)
+#define        MDOC_JOIN        (1 << 5)
 };
 
 enum   margserr {
 };
 
 enum   margserr {
@@ -107,6 +110,7 @@ __BEGIN_DECLS
 int              mdoc_macro(MACRO_PROT_ARGS);
 int              mdoc_word_alloc(struct mdoc *, 
                        int, int, const char *);
 int              mdoc_macro(MACRO_PROT_ARGS);
 int              mdoc_word_alloc(struct mdoc *, 
                        int, int, const char *);
+void             mdoc_word_append(struct mdoc *, const char *);
 int              mdoc_elem_alloc(struct mdoc *, int, int, 
                        enum mdoct, struct mdoc_arg *);
 int              mdoc_block_alloc(struct mdoc *, int, int, 
 int              mdoc_elem_alloc(struct mdoc *, int, int, 
                        enum mdoct, struct mdoc_arg *);
 int              mdoc_block_alloc(struct mdoc *, int, int, 
index 24ffc63..e6e1c28 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man.c,v 1.119 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: man.c,v 1.121 2013/11/10 22:54:40 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -40,7 +40,8 @@ const char *const __man_macronames[MAN_MAX] = {
        "RI",           "na",           "sp",           "nf",
        "fi",           "RE",           "RS",           "DT",
        "UC",           "PD",           "AT",           "in",
        "RI",           "na",           "sp",           "nf",
        "fi",           "RE",           "RS",           "DT",
        "UC",           "PD",           "AT",           "in",
-       "ft",           "OP",           "EX",           "EE"
+       "ft",           "OP",           "EX",           "EE",
+       "UR",           "UE"
        };
 
 const  char * const *man_macronames = __man_macronames;
        };
 
 const  char * const *man_macronames = __man_macronames;
@@ -428,16 +429,22 @@ man_ptext(struct man *man, int line, char *buf, int offs)
                return(man_descope(man, line, offs));
        }
 
                return(man_descope(man, line, offs));
        }
 
-       /* Pump blank lines directly into the backend. */
-
        for (i = offs; ' ' == buf[i]; i++)
                /* Skip leading whitespace. */ ;
 
        for (i = offs; ' ' == buf[i]; i++)
                /* Skip leading whitespace. */ ;
 
+       /*
+        * Blank lines are ignored right after headings
+        * but add a single vertical space elsewhere.
+        */
+
        if ('\0' == buf[i]) {
                /* Allocate a blank entry. */
        if ('\0' == buf[i]) {
                /* Allocate a blank entry. */
-               if ( ! man_elem_alloc(man, line, offs, MAN_sp))
-                       return(0);
-               man->next = MAN_NEXT_SIBLING;
+               if (MAN_SH != man->last->tok &&
+                   MAN_SS != man->last->tok) {
+                       if ( ! man_elem_alloc(man, line, offs, MAN_sp))
+                               return(0);
+                       man->next = MAN_NEXT_SIBLING;
+               }
                return(1);
        }
 
                return(1);
        }
 
index e85da9a..ef9480f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man.h,v 1.61 2012/06/02 20:16:23 schwarze Exp $ */
+/*     $Id: man.h,v 1.62 2013/10/17 20:54:58 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -54,6 +54,8 @@ enum  mant {
        MAN_OP,
        MAN_EX,
        MAN_EE,
        MAN_OP,
        MAN_EX,
        MAN_EE,
+       MAN_UR,
+       MAN_UE,
        MAN_MAX
 };
 
        MAN_MAX
 };
 
index 100188b..2c4e220 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: man_html.c,v 1.89 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: man_html.c,v 1.90 2013/10/17 20:54:58 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -70,6 +71,7 @@ static        int               man_RS_pre(MAN_ARGS);
 static int               man_SH_pre(MAN_ARGS);
 static int               man_SM_pre(MAN_ARGS);
 static int               man_SS_pre(MAN_ARGS);
 static int               man_SH_pre(MAN_ARGS);
 static int               man_SM_pre(MAN_ARGS);
 static int               man_SS_pre(MAN_ARGS);
+static int               man_UR_pre(MAN_ARGS);
 static int               man_alt_pre(MAN_ARGS);
 static int               man_br_pre(MAN_ARGS);
 static int               man_ign_pre(MAN_ARGS);
 static int               man_alt_pre(MAN_ARGS);
 static int               man_br_pre(MAN_ARGS);
 static int               man_ign_pre(MAN_ARGS);
@@ -115,6 +117,8 @@ static      const struct htmlman mans[MAN_MAX] = {
        { man_OP_pre, NULL }, /* OP */
        { man_literal_pre, NULL }, /* EX */
        { man_literal_pre, NULL }, /* EE */
        { man_OP_pre, NULL }, /* OP */
        { man_literal_pre, NULL }, /* EX */
        { man_literal_pre, NULL }, /* EE */
+       { man_UR_pre, NULL }, /* UR */
+       { NULL, NULL }, /* UE */
 };
 
 /*
 };
 
 /*
@@ -688,3 +692,27 @@ man_RS_pre(MAN_ARGS)
        print_otag(h, TAG_DIV, 1, &tag);
        return(1);
 }
        print_otag(h, TAG_DIV, 1, &tag);
        return(1);
 }
+
+/* ARGSUSED */
+static int
+man_UR_pre(MAN_ARGS)
+{
+       struct htmlpair          tag[2];
+
+       n = n->child;
+       assert(MAN_HEAD == n->type);
+       if (n->nchild) {
+               assert(MAN_TEXT == n->child->type);
+               PAIR_CLASS_INIT(&tag[0], "link-ext");
+               PAIR_HREF_INIT(&tag[1], n->child->string);
+               print_otag(h, TAG_A, 2, tag);
+       }
+
+       assert(MAN_BODY == n->next->type);
+       if (n->next->nchild)
+               n = n->next;
+
+       print_man_nodelist(man, n->child, mh, h);
+
+       return(0);
+}
index 6631f14..479d048 100644 (file)
@@ -1,7 +1,8 @@
-/*     $Id: man_macro.c,v 1.75 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: man_macro.c,v 1.79 2013/12/25 00:50:05 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -88,6 +89,8 @@ const struct man_macro __man_macros[MAN_MAX] = {
        { in_line_eoln, 0 }, /* OP */
        { in_line_eoln, MAN_BSCOPE }, /* EX */
        { in_line_eoln, MAN_BSCOPE }, /* EE */
        { in_line_eoln, 0 }, /* OP */
        { in_line_eoln, MAN_BSCOPE }, /* EX */
        { in_line_eoln, MAN_BSCOPE }, /* EE */
+       { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
+       { blk_close, 0 }, /* UE */
 };
 
 const  struct man_macro * const man_macros = __man_macros;
 };
 
 const  struct man_macro * const man_macros = __man_macros;
@@ -284,6 +287,9 @@ blk_close(MACRO_PROT_ARGS)
        case (MAN_RE):
                ntok = MAN_RS;
                break;
        case (MAN_RE):
                ntok = MAN_RS;
                break;
+       case (MAN_UE):
+               ntok = MAN_UR;
+               break;
        default:
                abort();
                /* NOTREACHED */
        default:
                abort();
                /* NOTREACHED */
@@ -293,10 +299,12 @@ blk_close(MACRO_PROT_ARGS)
                if (ntok == nn->tok && MAN_BLOCK == nn->type)
                        break;
 
                if (ntok == nn->tok && MAN_BLOCK == nn->type)
                        break;
 
-       if (NULL != nn)
-               man_unscope(man, nn, MANDOCERR_MAX);
-       else
+       if (NULL == nn) {
                man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);
                man_pmsg(man, line, ppos, MANDOCERR_NOSCOPE);
+               if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
+                       return(0);
+       } else 
+               man_unscope(man, nn, MANDOCERR_MAX);
 
        return(1);
 }
 
        return(1);
 }
@@ -425,6 +433,15 @@ in_line_eoln(MACRO_PROT_ARGS)
        }
 
        /*
        }
 
        /*
+        * Append MAN_EOS in case the last snipped argument
+        * ends with a dot, e.g. `.IR syslog (3).'
+        */
+
+       if (n != man->last &&
+           mandoc_eos(man->last->string, strlen(man->last->string), 0))
+               man->last->flags |= MAN_EOS;
+
+       /*
         * If no arguments are specified and this is MAN_SCOPED (i.e.,
         * next-line scoped), then set our mode to indicate that we're
         * waiting for terms to load into our context.
         * If no arguments are specified and this is MAN_SCOPED (i.e.,
         * next-line scoped), then set our mode to indicate that we're
         * waiting for terms to load into our context.
index db5719c..4bd6244 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_term.c,v 1.136 2013/01/05 22:19:12 schwarze Exp $ */
+/*     $Id: man_term.c,v 1.139 2013/12/22 23:34:13 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -78,6 +78,7 @@ static        int               pre_RS(DECL_ARGS);
 static int               pre_SH(DECL_ARGS);
 static int               pre_SS(DECL_ARGS);
 static int               pre_TP(DECL_ARGS);
 static int               pre_SH(DECL_ARGS);
 static int               pre_SS(DECL_ARGS);
 static int               pre_TP(DECL_ARGS);
+static int               pre_UR(DECL_ARGS);
 static int               pre_alternate(DECL_ARGS);
 static int               pre_ft(DECL_ARGS);
 static int               pre_ign(DECL_ARGS);
 static int               pre_alternate(DECL_ARGS);
 static int               pre_ft(DECL_ARGS);
 static int               pre_ign(DECL_ARGS);
@@ -91,6 +92,7 @@ static        void              post_RS(DECL_ARGS);
 static void              post_SH(DECL_ARGS);
 static void              post_SS(DECL_ARGS);
 static void              post_TP(DECL_ARGS);
 static void              post_SH(DECL_ARGS);
 static void              post_SS(DECL_ARGS);
 static void              post_TP(DECL_ARGS);
+static void              post_UR(DECL_ARGS);
 
 static const struct termact termacts[MAN_MAX] = {
        { pre_sp, NULL, MAN_NOTEXT }, /* br */
 
 static const struct termact termacts[MAN_MAX] = {
        { pre_sp, NULL, MAN_NOTEXT }, /* br */
@@ -129,6 +131,8 @@ static      const struct termact termacts[MAN_MAX] = {
        { pre_OP, NULL, 0 }, /* OP */
        { pre_literal, NULL, 0 }, /* EX */
        { pre_literal, NULL, 0 }, /* EE */
        { pre_OP, NULL, 0 }, /* OP */
        { pre_literal, NULL, 0 }, /* EX */
        { pre_literal, NULL, 0 }, /* EE */
+       { pre_UR, post_UR, 0 }, /* UR */
+       { NULL, NULL, 0 }, /* UE */
 };
 
 
 };
 
 
@@ -261,7 +265,8 @@ pre_literal(DECL_ARGS)
        if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) {
                p->offset = p->rmargin;
                p->rmargin = p->maxrmargin;
        if (MAN_HP == n->parent->tok && p->rmargin < p->maxrmargin) {
                p->offset = p->rmargin;
                p->rmargin = p->maxrmargin;
-               p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE);
+               p->trailspace = 0;
+               p->flags &= ~TERMP_NOBREAK;
                p->flags |= TERMP_NOSPACE;
        }
 
                p->flags |= TERMP_NOSPACE;
        }
 
@@ -531,7 +536,7 @@ pre_HP(DECL_ARGS)
 
        if ( ! (MANT_LITERAL & mt->fl)) {
                p->flags |= TERMP_NOBREAK;
 
        if ( ! (MANT_LITERAL & mt->fl)) {
                p->flags |= TERMP_NOBREAK;
-               p->flags |= TERMP_TWOSPACE;
+               p->trailspace = 2;
        }
 
        len = mt->lmargin[mt->lmargincur];
        }
 
        len = mt->lmargin[mt->lmargincur];
@@ -566,7 +571,7 @@ post_HP(DECL_ARGS)
        case (MAN_BODY):
                term_newln(p);
                p->flags &= ~TERMP_NOBREAK;
        case (MAN_BODY):
                term_newln(p);
                p->flags &= ~TERMP_NOBREAK;
-               p->flags &= ~TERMP_TWOSPACE;
+               p->trailspace = 0;
                p->offset = mt->offset;
                p->rmargin = p->maxrmargin;
                break;
                p->offset = mt->offset;
                p->rmargin = p->maxrmargin;
                break;
@@ -609,6 +614,7 @@ pre_IP(DECL_ARGS)
                break;
        case (MAN_HEAD):
                p->flags |= TERMP_NOBREAK;
                break;
        case (MAN_HEAD):
                p->flags |= TERMP_NOBREAK;
+               p->trailspace = 1;
                break;
        case (MAN_BLOCK):
                print_bvspace(p, n, mt->pardist);
                break;
        case (MAN_BLOCK):
                print_bvspace(p, n, mt->pardist);
@@ -671,10 +677,12 @@ post_IP(DECL_ARGS)
        case (MAN_HEAD):
                term_flushln(p);
                p->flags &= ~TERMP_NOBREAK;
        case (MAN_HEAD):
                term_flushln(p);
                p->flags &= ~TERMP_NOBREAK;
+               p->trailspace = 0;
                p->rmargin = p->maxrmargin;
                break;
        case (MAN_BODY):
                term_newln(p);
                p->rmargin = p->maxrmargin;
                break;
        case (MAN_BODY):
                term_newln(p);
+               p->offset = mt->offset;
                break;
        default:
                break;
                break;
        default:
                break;
@@ -693,6 +701,7 @@ pre_TP(DECL_ARGS)
        switch (n->type) {
        case (MAN_HEAD):
                p->flags |= TERMP_NOBREAK;
        switch (n->type) {
        case (MAN_HEAD):
                p->flags |= TERMP_NOBREAK;
+               p->trailspace = 1;
                break;
        case (MAN_BODY):
                p->flags |= TERMP_NOSPACE;
                break;
        case (MAN_BODY):
                p->flags |= TERMP_NOSPACE;
@@ -740,8 +749,8 @@ pre_TP(DECL_ARGS)
        case (MAN_BODY):
                p->offset = mt->offset + len;
                p->rmargin = p->maxrmargin;
        case (MAN_BODY):
                p->offset = mt->offset + len;
                p->rmargin = p->maxrmargin;
+               p->trailspace = 0;
                p->flags &= ~TERMP_NOBREAK;
                p->flags &= ~TERMP_NOBREAK;
-               p->flags &= ~TERMP_TWOSPACE;
                break;
        default:
                break;
                break;
        default:
                break;
@@ -762,6 +771,7 @@ post_TP(DECL_ARGS)
                break;
        case (MAN_BODY):
                term_newln(p);
                break;
        case (MAN_BODY):
                term_newln(p);
+               p->offset = mt->offset;
                break;
        default:
                break;
                break;
        default:
                break;
@@ -939,6 +949,32 @@ post_RS(DECL_ARGS)
                mt->lmargincur = mt->lmarginsz;
 }
 
                mt->lmargincur = mt->lmarginsz;
 }
 
+/* ARGSUSED */
+static int
+pre_UR(DECL_ARGS)
+{
+
+       return (MAN_HEAD != n->type);
+}
+
+/* ARGSUSED */
+static void
+post_UR(DECL_ARGS)
+{
+
+       if (MAN_BLOCK != n->type)
+               return;
+
+       term_word(p, "<");
+       p->flags |= TERMP_NOSPACE;
+
+       if (NULL != n->child->child)
+               print_man_node(p, mt, n->child->child, meta);
+
+       p->flags |= TERMP_NOSPACE;
+       term_word(p, ">");
+}
+
 static void
 print_man_node(DECL_ARGS)
 {
 static void
 print_man_node(DECL_ARGS)
 {
@@ -1069,6 +1105,7 @@ print_man_foot(struct termp *p, const void *arg)
        /* Bottom left corner: manual source. */
 
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
        /* Bottom left corner: manual source. */
 
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
+       p->trailspace = 1;
        p->offset = 0;
        p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
 
        p->offset = 0;
        p->rmargin = (p->maxrmargin - datelen + term_len(p, 1)) / 2;
 
@@ -1091,6 +1128,7 @@ print_man_foot(struct termp *p, const void *arg)
 
        p->flags &= ~TERMP_NOBREAK;
        p->flags |= TERMP_NOSPACE;
 
        p->flags &= ~TERMP_NOBREAK;
        p->flags |= TERMP_NOSPACE;
+       p->trailspace = 0;
        p->offset = p->rmargin;
        p->rmargin = p->maxrmargin;
 
        p->offset = p->rmargin;
        p->rmargin = p->maxrmargin;
 
@@ -1122,6 +1160,7 @@ print_man_head(struct termp *p, const void *arg)
        titlen = term_strlen(p, title);
 
        p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
        titlen = term_strlen(p, title);
 
        p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
+       p->trailspace = 1;
        p->offset = 0;
        p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
            (p->maxrmargin - 
        p->offset = 0;
        p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
            (p->maxrmargin - 
@@ -1144,6 +1183,7 @@ print_man_head(struct termp *p, const void *arg)
        /* Top right corner: title and section, again. */
 
        p->flags &= ~TERMP_NOBREAK;
        /* Top right corner: title and section, again. */
 
        p->flags &= ~TERMP_NOBREAK;
+       p->trailspace = 0;
        if (p->rmargin + titlen <= p->maxrmargin) {
                p->flags |= TERMP_NOSPACE;
                p->offset = p->rmargin;
        if (p->rmargin + titlen <= p->maxrmargin) {
                p->flags |= TERMP_NOSPACE;
                p->offset = p->rmargin;
index 7a9deed..da2e557 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: man_validate.c,v 1.85 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: man_validate.c,v 1.86 2013/10/17 20:54:58 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -49,6 +49,7 @@ static        int       check_eq2(CHKARGS);
 static int       check_le1(CHKARGS);
 static int       check_ge2(CHKARGS);
 static int       check_le5(CHKARGS);
 static int       check_le1(CHKARGS);
 static int       check_ge2(CHKARGS);
 static int       check_le5(CHKARGS);
+static int       check_head1(CHKARGS);
 static int       check_par(CHKARGS);
 static int       check_part(CHKARGS);
 static int       check_root(CHKARGS);
 static int       check_par(CHKARGS);
 static int       check_part(CHKARGS);
 static int       check_root(CHKARGS);
@@ -80,6 +81,7 @@ static        v_check   posts_sec[] = { post_sec, NULL };
 static v_check   posts_sp[] = { post_vs, check_le1, NULL };
 static v_check   posts_th[] = { check_ge2, check_le5, post_TH, NULL };
 static v_check   posts_uc[] = { post_UC, NULL };
 static v_check   posts_sp[] = { post_vs, check_le1, NULL };
 static v_check   posts_th[] = { check_ge2, check_le5, post_TH, NULL };
 static v_check   posts_uc[] = { post_UC, NULL };
+static v_check   posts_ur[] = { check_head1, check_part, NULL };
 static v_check   pres_sec[] = { pre_sec, NULL };
 
 static const struct man_valid man_valids[MAN_MAX] = {
 static v_check   pres_sec[] = { pre_sec, NULL };
 
 static const struct man_valid man_valids[MAN_MAX] = {
@@ -119,6 +121,8 @@ static      const struct man_valid man_valids[MAN_MAX] = {
        { NULL, posts_eq2 }, /* OP */
        { NULL, posts_nf }, /* EX */
        { NULL, posts_fi }, /* EE */
        { NULL, posts_eq2 }, /* OP */
        { NULL, posts_nf }, /* EX */
        { NULL, posts_fi }, /* EE */
+       { NULL, posts_ur }, /* UR */
+       { NULL, NULL }, /* UE */
 };
 
 
 };
 
 
@@ -246,6 +250,17 @@ INEQ_DEFINE(2, >=, ge2)
 INEQ_DEFINE(5, <=, le5)
 
 static int
 INEQ_DEFINE(5, <=, le5)
 
 static int
+check_head1(CHKARGS)
+{
+
+       if (MAN_HEAD == n->type && 1 != n->nchild)
+               mandoc_vmsg(MANDOCERR_ARGCOUNT, man->parse, n->line,
+                   n->pos, "line arguments eq 1 (have %d)", n->nchild);
+
+       return(1);
+}
+
+static int
 post_ft(CHKARGS)
 {
        char    *cp;
 post_ft(CHKARGS)
 {
        char    *cp;
index bc6aa90..fe6503d 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc.3,v 1.20 2013/09/16 22:54:38 schwarze Exp $
+.\"    $Id: mandoc.3,v 1.22 2013/10/06 17:01:52 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: September 16 2013 $
+.Dd $Mdocdate: October 6 2013 $
 .Dt MANDOC 3
 .Os
 .Sh NAME
 .Dt MANDOC 3
 .Os
 .Sh NAME
 .Nm mparse_strlevel
 .Nd mandoc macro compiler library
 .Sh LIBRARY
 .Nm mparse_strlevel
 .Nd mandoc macro compiler library
 .Sh LIBRARY
-.Lb mandoc
+.Lb libmandoc
 .Sh SYNOPSIS
 .In man.h
 .In mdoc.h
 .In mandoc.h
 .Ft "enum mandoc_esc"
 .Fo mandoc_escape
 .Sh SYNOPSIS
 .In man.h
 .In mdoc.h
 .In mandoc.h
 .Ft "enum mandoc_esc"
 .Fo mandoc_escape
-.Fa "const char **end"
-.Fa "const char **start"
+.Fa "const char const **end"
+.Fa "const char const **start"
 .Fa "int *sz"
 .Fc
 .Ft "const struct man_meta *"
 .Fa "int *sz"
 .Fc
 .Ft "const struct man_meta *"
index df51022..da738f2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.c,v 1.68 2013/08/08 20:07:47 schwarze Exp $ */
+/*     $Id: mandoc.c,v 1.74 2013/12/30 18:30:32 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -93,12 +93,23 @@ mandoc_escape(const char **end, const char **start, int *sz)
        case ('C'):
                if ('\'' != **start)
                        return(ESCAPE_ERROR);
        case ('C'):
                if ('\'' != **start)
                        return(ESCAPE_ERROR);
-               gly = ESCAPE_SPECIAL;
                *start = ++*end;
                *start = ++*end;
+               if ('u' == (*start)[0] && '\'' != (*start)[1])
+                       gly = ESCAPE_UNICODE;
+               else
+                       gly = ESCAPE_SPECIAL;
                term = '\'';
                break;
 
        /*
                term = '\'';
                break;
 
        /*
+        * Escapes taking no arguments at all.
+        */
+       case ('d'):
+               /* FALLTHROUGH */
+       case ('u'):
+               return(ESCAPE_IGNORE);
+
+       /*
         * The \z escape is supposed to output the following
         * character without advancing the cursor position.  
         * Since we are mostly dealing with terminal mode,
         * The \z escape is supposed to output the following
         * character without advancing the cursor position.  
         * Since we are mostly dealing with terminal mode,
@@ -154,12 +165,16 @@ mandoc_escape(const char **end, const char **start, int *sz)
                /* FALLTHROUGH */
        case ('b'):
                /* FALLTHROUGH */
                /* FALLTHROUGH */
        case ('b'):
                /* FALLTHROUGH */
+       case ('B'):
+               /* FALLTHROUGH */
        case ('D'):
                /* FALLTHROUGH */
        case ('o'):
                /* FALLTHROUGH */
        case ('R'):
                /* FALLTHROUGH */
        case ('D'):
                /* FALLTHROUGH */
        case ('o'):
                /* FALLTHROUGH */
        case ('R'):
                /* FALLTHROUGH */
+       case ('w'):
+               /* FALLTHROUGH */
        case ('X'):
                /* FALLTHROUGH */
        case ('Z'):
        case ('X'):
                /* FALLTHROUGH */
        case ('Z'):
@@ -174,8 +189,6 @@ mandoc_escape(const char **end, const char **start, int *sz)
         * These escapes are of the form \X'N', where 'X' is the trigger
         * and 'N' resolves to a numerical expression.
         */
         * These escapes are of the form \X'N', where 'X' is the trigger
         * and 'N' resolves to a numerical expression.
         */
-       case ('B'):
-               /* FALLTHROUGH */
        case ('h'):
                /* FALLTHROUGH */
        case ('H'):
        case ('h'):
                /* FALLTHROUGH */
        case ('H'):
@@ -183,19 +196,15 @@ mandoc_escape(const char **end, const char **start, int *sz)
        case ('L'):
                /* FALLTHROUGH */
        case ('l'):
        case ('L'):
                /* FALLTHROUGH */
        case ('l'):
-               gly = ESCAPE_NUMBERED;
                /* FALLTHROUGH */
        case ('S'):
                /* FALLTHROUGH */
        case ('v'):
                /* FALLTHROUGH */
                /* FALLTHROUGH */
        case ('S'):
                /* FALLTHROUGH */
        case ('v'):
                /* FALLTHROUGH */
-       case ('w'):
-               /* FALLTHROUGH */
        case ('x'):
                if ('\'' != **start)
                        return(ESCAPE_ERROR);
        case ('x'):
                if ('\'' != **start)
                        return(ESCAPE_ERROR);
-               if (ESCAPE_ERROR == gly)
-                       gly = ESCAPE_IGNORE;
+               gly = ESCAPE_IGNORE;
                *start = ++*end;
                term = '\'';
                break;
                *start = ++*end;
                term = '\'';
                break;
@@ -416,10 +425,10 @@ mandoc_strdup(const char *ptr)
  * Parse a quoted or unquoted roff-style request or macro argument.
  * Return a pointer to the parsed argument, which is either the original
  * pointer or advanced by one byte in case the argument is quoted.
  * Parse a quoted or unquoted roff-style request or macro argument.
  * Return a pointer to the parsed argument, which is either the original
  * pointer or advanced by one byte in case the argument is quoted.
- * Null-terminate the argument in place.
+ * NUL-terminate the argument in place.
  * Collapse pairs of quotes inside quoted arguments.
  * Advance the argument pointer to the next argument,
  * Collapse pairs of quotes inside quoted arguments.
  * Advance the argument pointer to the next argument,
- * or to the null byte terminating the argument line.
+ * or to the NUL byte terminating the argument line.
  */
 char *
 mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
  */
 char *
 mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
@@ -490,7 +499,7 @@ mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos)
        if (1 == quoted)
                mandoc_msg(MANDOCERR_BADQUOTE, parse, ln, *pos, NULL);
 
        if (1 == quoted)
                mandoc_msg(MANDOCERR_BADQUOTE, parse, ln, *pos, NULL);
 
-       /* Null-terminate this argument and move to the next one. */
+       /* NUL-terminate this argument and move to the next one. */
        if (pairs)
                cp[-pairs] = '\0';
        if ('\0' != *cp) {
        if (pairs)
                cp[-pairs] = '\0';
        if ('\0' != *cp) {
index c2406e9..4c6a32f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.h,v 1.110 2013/09/16 00:25:07 schwarze Exp $ */
+/*     $Id: mandoc.h,v 1.112 2013/12/30 18:30:32 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
index 23ccc0a..8d83566 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mandoc_char.7,v 1.53 2013/07/13 19:41:16 schwarze Exp $
+.\"    $Id: mandoc_char.7,v 1.56 2013/12/26 17:23:42 schwarze Exp $
 .\"
 .\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
 .\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org>
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -16,7 +16,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: July 13 2013 $
+.Dd $Mdocdate: December 26 2013 $
 .Dt MANDOC_CHAR 7
 .Os
 .Sh NAME
 .Dt MANDOC_CHAR 7
 .Os
 .Sh NAME
@@ -98,26 +98,27 @@ in literal context, and when none of the following special cases apply,
 just use the normal space character
 .Pq Sq \  .
 .Pp
 just use the normal space character
 .Pq Sq \  .
 .Pp
-When filling text, lines may be broken between words, i.e. at space
+When filling text, output lines may be broken between words, i.e. at space
 characters.
 To prevent a line break between two particular words,
 characters.
 To prevent a line break between two particular words,
-use the non-breaking space escape sequence
-.Pq Sq \e~
+use the unpaddable non-breaking space escape sequence
+.Pq Sq \e\ \&
 instead of the normal space character.
 For example, the input string
 instead of the normal space character.
 For example, the input string
-.Dq number\e~1
+.Dq number\e1
 will be kept together as
 will be kept together as
-.Dq number\~1
+.Dq number\ 1
 on the same output line.
 .Pp
 On request and macro lines, the normal space character serves as an
 argument delimiter.
 on the same output line.
 .Pp
 On request and macro lines, the normal space character serves as an
 argument delimiter.
-To include whitespace into arguments, quoting is usually the best choice.
-In some cases, using either the non-breaking
-.Pq Sq \e~
-or the breaking
+To include whitespace into arguments, quoting is usually the best choice;
+see the MACRO SYNTAX section in
+.Xr roff 7 .
+In some cases, using the non-breaking space escape sequence
 .Pq Sq \e\ \&
 .Pq Sq \e\ \&
-space escape sequence may be preferable.
+may be preferable.
+.Pp
 To escape macro names and to protect whitespace at the end
 of input lines, the zero-width space
 .Pq Sq \e&
 To escape macro names and to protect whitespace at the end
 of input lines, the zero-width space
 .Pq Sq \e&
@@ -194,14 +195,13 @@ manual.
 Spacing:
 .Bl -column "Input" "Description" -offset indent -compact
 .It Em Input Ta Em Description
 Spacing:
 .Bl -column "Input" "Description" -offset indent -compact
 .It Em Input Ta Em Description
-.It \e~      Ta non-breaking, non-collapsing space
-.It \e       Ta breaking, non-collapsing n-width space
-.It \e^      Ta zero-width space
-.It \e%      Ta zero-width space
+.It Sq \e\ \& Ta unpaddable non-breaking space
+.It \e~      Ta paddable non-breaking space
+.It \e0      Ta unpaddable, breaking digit-width space
+.It \e|      Ta one-sixth \e(em narrow space, zero width in nroff mode
+.It \e^      Ta one-twelfth \e(em half-narrow space, zero width in nroff
 .It \e&      Ta zero-width space
 .It \e&      Ta zero-width space
-.It \e|      Ta zero-width space
-.It \e0      Ta breaking, non-collapsing digit-width space
-.It \ec      Ta removes any trailing space (if applicable)
+.It \e%      Ta zero-width space allowing hyphenation
 .El
 .Pp
 Lines:
 .El
 .Pp
 Lines:
@@ -655,13 +655,18 @@ manual.
 .It \e*(Ai   Ta \*(Ai       Ta ANSI standard name
 .El
 .Sh UNICODE CHARACTERS
 .It \e*(Ai   Ta \*(Ai       Ta ANSI standard name
 .El
 .Sh UNICODE CHARACTERS
-The escape sequence
+The escape sequences
 .Pp
 .Pp
-.Dl \e[uXXXX]
+.Dl \e[uXXXX] and \eC'uXXXX'
 .Pp
 .Pp
-is interpreted as a Unicode codepoint.
+are interpreted as Unicode codepoints.
 The codepoint must be in the range above U+0080 and less than U+10FFFF.
 The codepoint must be in the range above U+0080 and less than U+10FFFF.
-For compatibility, points must be zero-padded to four characters; if
+For compatibility, the hexadecimal digits
+.Sq A
+to
+.Sq F
+must be given as uppercase characters,
+and points must be zero-padded to four characters; if
 greater than four characters, no zero padding is allowed.
 Unicode surrogates are not allowed.
 .\" .Pp
 greater than four characters, no zero padding is allowed.
 Unicode surrogates are not allowed.
 .\" .Pp
@@ -730,9 +735,9 @@ The
 manual page was written by
 .An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
 .Sh CAVEATS
 manual page was written by
 .An Kristaps Dzonsons Aq Mt kristaps@bsd.lv .
 .Sh CAVEATS
-The
+The predefined string
 .Sq \e*(Ba
 .Sq \e*(Ba
-escape mimics the behaviour of the
+mimics the behaviour of the
 .Sq \&|
 character in
 .Xr mdoc 7 ;
 .Sq \&|
 character in
 .Xr mdoc 7 ;
index 028377c..a7491ca 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandocdb.c,v 1.49.2.7 2013/10/02 21:03:26 schwarze Exp $ */
+/*     $Id: mandocdb.c,v 1.49.2.10 2013/11/21 01:53:48 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
 #include <string.h>
 #include <unistd.h>
 
 #include <string.h>
 #include <unistd.h>
 
-#if defined(__linux__) || defined(__sun)
-# include <endian.h>
-# include <db_185.h>
-#elif defined(__APPLE__)
+#if defined(__APPLE__)
 # include <libkern/OSByteOrder.h>
 # include <libkern/OSByteOrder.h>
-# include <db.h>
+#elif defined(__linux__)
+# include <endian.h>
+#elif defined(__sun)
+# include <sys/byteorder.h>
+# include <sys/stat.h>
 #else
 # include <sys/endian.h>
 #else
 # include <sys/endian.h>
-# include <db.h>
 #endif
 
 #endif
 
-#if defined(__sun)
-#include <sys/stat.h>
+#if defined(__linux__) || defined(__sun)
+# include <db_185.h>
+#else
+# include <db.h>
 #endif
 
 #include "man.h"
 #endif
 
 #include "man.h"
@@ -620,6 +622,8 @@ index_merge(const struct of *of, struct mparse *mp,
        uint64_t         vbuf[2];
        char             type;
 
        uint64_t         vbuf[2];
        char             type;
 
+       static char      emptystring[] = "";
+
        if (warnings) {
                files = NULL;
                hash_reset(&files);
        if (warnings) {
                files = NULL;
                hash_reset(&files);
@@ -732,13 +736,13 @@ index_merge(const struct of *of, struct mparse *mp,
                        }
                        buf_appendb(buf, ")", 2);
                        for (p = buf->cp; '\0' != *p; p++)
                        }
                        buf_appendb(buf, ")", 2);
                        for (p = buf->cp; '\0' != *p; p++)
-                               *p = tolower(*p);
+                               *p = tolower((unsigned char)*p);
                        key.data = buf->cp;
                        key.size = buf->len;
                        val.data = NULL;
                        val.size = 0;
                        if (0 == skip)
                        key.data = buf->cp;
                        key.size = buf->len;
                        val.data = NULL;
                        val.size = 0;
                        if (0 == skip)
-                               val.data = "";
+                               val.data = emptystring;
                        else {
                                ch = (*files->get)(files, &key, &val, 0);
                                if (ch < 0) {
                        else {
                                ch = (*files->get)(files, &key, &val, 0);
                                if (ch < 0) {
index 9008932..c33e0ec 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: manpath.c,v 1.11 2013/06/05 02:00:26 schwarze Exp $ */
+/*     $Id: manpath.c,v 1.12 2013/11/21 01:49:18 schwarze Exp $ */
 /*
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
  * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv>
@@ -209,7 +209,7 @@ manpath_manconf(struct manpaths *dirs, const char *file)
                if (strncmp(MAN_CONF_KEY, p, keysz))
                        continue;
                p += keysz;
                if (strncmp(MAN_CONF_KEY, p, keysz))
                        continue;
                p += keysz;
-               while (isspace(*p))
+               while (isspace((unsigned char)*p))
                        p++;
                if ('\0' == *p)
                        continue;
                        p++;
                if ('\0' == *p)
                        continue;
index 00e1a1a..165c76b 100644 (file)
@@ -1,7 +1,7 @@
-.\"    $Id: mdoc.7,v 1.220 2013/08/14 15:08:31 schwarze Exp $
+.\"    $Id: mdoc.7,v 1.223 2013/12/25 14:09:32 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2011, 2013 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
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 14 2013 $
+.Dd $Mdocdate: December 25 2013 $
 .Dt MDOC 7
 .Os
 .Sh NAME
 .Dt MDOC 7
 .Os
 .Sh NAME
@@ -477,6 +477,7 @@ in the alphabetical
 .Bl -column "Brq, Bro, Brc" description
 .It Sx \&Lb Ta function library (one argument)
 .It Sx \&In Ta include file (one argument)
 .Bl -column "Brq, Bro, Brc" description
 .It Sx \&Lb Ta function library (one argument)
 .It Sx \&In Ta include file (one argument)
+.It Sx \&Fd Ta other preprocessor directive (>0 arguments)
 .It Sx \&Ft Ta function type (>0 arguments)
 .It Sx \&Fo , \&Fc Ta function block: Ar funcname
 .It Sx \&Fn Ta function name:
 .It Sx \&Ft Ta function type (>0 arguments)
 .It Sx \&Fo , \&Fc Ta function block: Ar funcname
 .It Sx \&Fn Ta function name:
@@ -1407,9 +1408,12 @@ See also
 .Sx \&Er
 and
 .Sx \&Ev
 .Sx \&Er
 and
 .Sx \&Ev
-for special-purpose constants and
+for special-purpose constants,
 .Sx \&Va
 .Sx \&Va
-for variable symbols.
+for variable symbols, and
+.Sx \&Fd
+for listing preprocessor variable definitions in the
+.Em SYNOPSIS .
 .Ss \&Dx
 Format the
 .Dx
 .Ss \&Dx
 Format the
 .Dx
@@ -1570,15 +1574,32 @@ See also
 End a function context started by
 .Sx \&Fo .
 .Ss \&Fd
 End a function context started by
 .Sx \&Fo .
 .Ss \&Fd
-Historically used to document include files.
-This usage has been deprecated in favour of
+Preprocessor directive, in particular for listing it in the
+.Em SYNOPSIS .
+Historically, it was also used to document include files.
+The latter usage has been deprecated in favour of
 .Sx \&In .
 .Sx \&In .
-Do not use this macro.
+.Pp
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Fd
+.Li # Ns Ar directive
+.Op Ar argument ...
+.Ed
+.Pp
+Examples:
+.Dl \&.Fd #define sa_handler __sigaction_u.__sa_handler
+.Dl \&.Fd #define SIO_MAXNFDS
+.Dl \&.Fd #ifdef FS_DEBUG
+.Dl \&.Ft void
+.Dl \&.Fn dbg_open \(dqconst char *\(dq
+.Dl \&.Fd #endif
 .Pp
 See also
 .Pp
 See also
-.Sx MANUAL STRUCTURE
+.Sx MANUAL STRUCTURE ,
+.Sx \&In ,
 and
 and
-.Sx \&In .
+.Sx \&Dv .
 .Ss \&Fl
 Command-line flag or option.
 Used when listing arguments to command-line utilities.
 .Ss \&Fl
 Command-line flag or option.
 Used when listing arguments to command-line utilities.
@@ -1859,7 +1880,7 @@ section as described in
 .Pp
 Examples:
 .Dl \&.Lb libz
 .Pp
 Examples:
 .Dl \&.Lb libz
-.Dl \&.Lb mdoc
+.Dl \&.Lb libmandoc
 .Ss \&Li
 Denotes text that should be in a
 .Li literal
 .Ss \&Li
 Denotes text that should be in a
 .Li literal
@@ -2422,6 +2443,8 @@ The following standards are recognised:
 .St -xbd5
 .It \-xcu5
 .St -xcu5
 .St -xbd5
 .It \-xcu5
 .St -xcu5
+.It \-xsh4.2
+.St -xsh4.2
 .It \-xsh5
 .St -xsh5
 .It \-xns5
 .It \-xsh5
 .St -xsh5
 .It \-xns5
index df68229..87b3587 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: mdoc.c,v 1.203 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: mdoc.c,v 1.206 2013/12/24 19:11:46 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -295,12 +295,10 @@ mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs)
         * whether this mode is on or off.
         * Note that this mode is also switched by the Sh macro.
         */
         * whether this mode is on or off.
         * Note that this mode is also switched by the Sh macro.
         */
-       if (roff_regisset(mdoc->roff, REG_nS)) {
-               if (roff_regget(mdoc->roff, REG_nS))
-                       mdoc->flags |= MDOC_SYNOPSIS;
-               else
-                       mdoc->flags &= ~MDOC_SYNOPSIS;
-       }
+       if (roff_getreg(mdoc->roff, "nS"))
+               mdoc->flags |= MDOC_SYNOPSIS;
+       else
+               mdoc->flags &= ~MDOC_SYNOPSIS;
 
        return(roff_getcontrol(mdoc->roff, buf, &offs) ?
                        mdoc_pmacro(mdoc, ln, buf, offs) :
 
        return(roff_getcontrol(mdoc->roff, buf, &offs) ?
                        mdoc_pmacro(mdoc, ln, buf, offs) :
@@ -436,6 +434,7 @@ node_alloc(struct mdoc *mdoc, int line, int pos,
        p->sec = mdoc->lastsec;
        p->line = line;
        p->pos = pos;
        p->sec = mdoc->lastsec;
        p->line = line;
        p->pos = pos;
+       p->lastline = line;
        p->tok = tok;
        p->type = type;
 
        p->tok = tok;
        p->type = type;
 
@@ -584,6 +583,23 @@ mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p)
        return(1);
 }
 
        return(1);
 }
 
+void
+mdoc_word_append(struct mdoc *mdoc, const char *p)
+{
+       struct mdoc_node        *n;
+       char                    *addstr, *newstr;
+
+       n = mdoc->last;
+       addstr = roff_strdup(mdoc->roff, p);
+       if (-1 == asprintf(&newstr, "%s %s", n->string, addstr)) {
+               perror(NULL);
+               exit((int)MANDOCLEVEL_SYSERR);
+       }
+       free(addstr);
+       free(n->string);
+       n->string = newstr;
+       mdoc->next = MDOC_NEXT_SIBLING;
+}
 
 static void
 mdoc_node_free(struct mdoc_node *p)
 
 static void
 mdoc_node_free(struct mdoc_node *p)
index cc807d7..d0153b4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc.h,v 1.124 2012/11/16 17:16:55 schwarze Exp $ */
+/*     $Id: mdoc.h,v 1.125 2013/12/24 19:11:45 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -351,6 +351,7 @@ struct      mdoc_node {
        int               nchild; /* number children */
        int               line; /* parse line */
        int               pos; /* parse column */
        int               nchild; /* number children */
        int               line; /* parse line */
        int               pos; /* parse column */
+       int               lastline; /* the node ends on this line */
        enum mdoct        tok; /* tok or MDOC__MAX if none */
        int               flags;
 #define        MDOC_VALID       (1 << 0) /* has been validated */
        enum mdoct        tok; /* tok or MDOC__MAX if none */
        int               flags;
 #define        MDOC_VALID       (1 << 0) /* has been validated */
index 220260a..bb9bc6c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_argv.c,v 1.86 2012/11/18 00:05:35 schwarze Exp $ */
+/*     $Id: mdoc_argv.c,v 1.89 2013/12/25 00:50:05 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
@@ -260,7 +260,7 @@ static      const struct mdocarg mdocargs[MDOC_MAX] = {
        { ARGSFL_NONE, NULL }, /* %C */
        { ARGSFL_NONE, NULL }, /* Es */
        { ARGSFL_NONE, NULL }, /* En */
        { ARGSFL_NONE, NULL }, /* %C */
        { ARGSFL_NONE, NULL }, /* Es */
        { ARGSFL_NONE, NULL }, /* En */
-       { ARGSFL_NONE, NULL }, /* Dx */
+       { ARGSFL_DELIM, NULL }, /* Dx */
        { ARGSFL_NONE, NULL }, /* %Q */
        { ARGSFL_NONE, NULL }, /* br */
        { ARGSFL_NONE, NULL }, /* sp */
        { ARGSFL_NONE, NULL }, /* %Q */
        { ARGSFL_NONE, NULL }, /* br */
        { ARGSFL_NONE, NULL }, /* sp */
@@ -447,6 +447,7 @@ args(struct mdoc *mdoc, int line, int *pos,
                char *buf, enum argsflag fl, char **v)
 {
        char            *p, *pp;
                char *buf, enum argsflag fl, char **v)
 {
        char            *p, *pp;
+       int              pairs;
        enum margserr    rc;
 
        if ('\0' == buf[*pos]) {
        enum margserr    rc;
 
        if ('\0' == buf[*pos]) {
@@ -535,11 +536,13 @@ args(struct mdoc *mdoc, int line, int *pos,
                        /* Skip ahead. */ ;
 
                return(rc);
                        /* Skip ahead. */ ;
 
                return(rc);
-       } 
+       }
 
 
-       /* 
+       /*
         * Process a quoted literal.  A quote begins with a double-quote
         * and ends with a double-quote NOT preceded by a double-quote.
         * Process a quoted literal.  A quote begins with a double-quote
         * and ends with a double-quote NOT preceded by a double-quote.
+        * NUL-terminate the literal in place.
+        * Collapse pairs of quotes inside quoted literals.
         * Whitespace is NOT involved in literal termination.
         */
 
         * Whitespace is NOT involved in literal termination.
         */
 
@@ -550,13 +553,22 @@ args(struct mdoc *mdoc, int line, int *pos,
                if (MDOC_PPHRASE & mdoc->flags)
                        mdoc->flags |= MDOC_PHRASELIT;
 
                if (MDOC_PPHRASE & mdoc->flags)
                        mdoc->flags |= MDOC_PHRASELIT;
 
+               pairs = 0;
                for ( ; buf[*pos]; (*pos)++) {
                for ( ; buf[*pos]; (*pos)++) {
+                       /* Move following text left after quoted quotes. */
+                       if (pairs)
+                               buf[*pos - pairs] = buf[*pos];
                        if ('\"' != buf[*pos])
                                continue;
                        if ('\"' != buf[*pos])
                                continue;
+                       /* Unquoted quotes end quoted args. */
                        if ('\"' != buf[*pos + 1])
                                break;
                        if ('\"' != buf[*pos + 1])
                                break;
+                       /* Quoted quotes collapse. */
+                       pairs++;
                        (*pos)++;
                }
                        (*pos)++;
                }
+               if (pairs)
+                       buf[*pos - pairs] = '\0';
 
                if ('\0' == buf[*pos]) {
                        if (MDOC_PPHRASE & mdoc->flags)
 
                if ('\0' == buf[*pos]) {
                        if (MDOC_PPHRASE & mdoc->flags)
index ba93749..a7aa722 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_html.c,v 1.184 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: mdoc_html.c,v 1.186 2013/12/24 20:45:27 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -460,14 +460,10 @@ print_mdoc_node(MDOC_ARGS)
        }
 
        if (HTML_KEEP & h->flags) {
        }
 
        if (HTML_KEEP & h->flags) {
-               if (n->prev && n->prev->line != n->line) {
+               if (n->prev ? (n->prev->lastline != n->line) :
+                   (n->parent && n->parent->line != n->line)) {
                        h->flags &= ~HTML_KEEP;
                        h->flags |= HTML_PREKEEP;
                        h->flags &= ~HTML_KEEP;
                        h->flags |= HTML_PREKEEP;
-               } else if (NULL == n->prev) {
-                       if (n->parent && n->parent->line != n->line) {
-                               h->flags &= ~HTML_KEEP;
-                               h->flags |= HTML_PREKEEP;
-                       }
                }
        }
 
                }
        }
 
index 0a50486..2a63ca9 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: mdoc_macro.c,v 1.122 2013/09/15 18:26:46 schwarze Exp $ */
+/*     $Id: mdoc_macro.c,v 1.125 2013/12/24 20:45:27 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -51,8 +51,8 @@ static        int             in_line(MACRO_PROT_ARGS);
 static int             obsolete(MACRO_PROT_ARGS);
 static int             phrase_ta(MACRO_PROT_ARGS);
 
 static int             obsolete(MACRO_PROT_ARGS);
 static int             phrase_ta(MACRO_PROT_ARGS);
 
-static int             dword(struct mdoc *, int, int, 
-                               const char *, enum mdelim);
+static int             dword(struct mdoc *, int, int, const char *,
+                                enum mdelim, int);
 static int             append_delims(struct mdoc *, 
                                int, int *, char *);
 static enum mdoct      lookup(enum mdoct, const char *);
 static int             append_delims(struct mdoc *, 
                                int, int *, char *);
 static enum mdoct      lookup(enum mdoct, const char *);
@@ -70,128 +70,147 @@ static    int             rew_sub(enum mdoc_type, struct mdoc *,
                                enum mdoct, int, int);
 
 const  struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
                                enum mdoct, int, int);
 
 const  struct mdoc_macro __mdoc_macros[MDOC_MAX] = {
-       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ap */
+       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */
        { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
        { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
        { in_line_eoln, MDOC_PROLOGUE }, /* Os */
        { in_line_eoln, MDOC_PROLOGUE }, /* Dd */
        { in_line_eoln, MDOC_PROLOGUE }, /* Dt */
        { in_line_eoln, MDOC_PROLOGUE }, /* Os */
-       { blk_full, MDOC_PARSED }, /* Sh */
-       { blk_full, MDOC_PARSED }, /* Ss */ 
-       { in_line_eoln, 0 }, /* Pp */ 
-       { blk_part_imp, MDOC_PARSED }, /* D1 */
-       { blk_part_imp, MDOC_PARSED }, /* Dl */
+       { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Sh */
+       { blk_full, MDOC_PARSED | MDOC_JOIN }, /* Ss */
+       { in_line_eoln, 0 }, /* Pp */
+       { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* D1 */
+       { blk_part_imp, MDOC_PARSED | MDOC_JOIN }, /* Dl */
        { blk_full, MDOC_EXPLICIT }, /* Bd */
        { blk_full, MDOC_EXPLICIT }, /* Bd */
-       { blk_exp_close, MDOC_EXPLICIT }, /* Ed */
+       { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */
        { blk_full, MDOC_EXPLICIT }, /* Bl */
        { blk_full, MDOC_EXPLICIT }, /* Bl */
-       { blk_exp_close, MDOC_EXPLICIT }, /* El */
-       { blk_full, MDOC_PARSED }, /* It */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* An */
+       { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* El */
+       { blk_full, MDOC_PARSED | MDOC_JOIN }, /* It */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ad */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* An */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ar */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cd */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Cm */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */ 
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Dv */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Er */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ev */
        { in_line_eoln, 0 }, /* Ex */
        { in_line_eoln, 0 }, /* Ex */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */ 
-       { in_line_eoln, 0 }, /* Fd */ 
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fa */
+       { in_line_eoln, 0 }, /* Fd */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fl */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */ 
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Fn */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ft */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ic */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* In */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Li */
-       { blk_full, 0 }, /* Nd */ 
-       { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */ 
+       { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Li */
+       { blk_full, MDOC_JOIN }, /* Nd */
+       { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Nm */
        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
        { obsolete, 0 }, /* Ot */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
        { in_line_eoln, 0 }, /* Rv */
        { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Op */
        { obsolete, 0 }, /* Ot */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Pa */
        { in_line_eoln, 0 }, /* Rv */
-       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 
+       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Va */
-       { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */ 
+       { ctx_synopsis, MDOC_CALLABLE | MDOC_PARSED }, /* Vt */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Xr */
-       { in_line_eoln, 0 }, /* %A */
-       { in_line_eoln, 0 }, /* %B */
-       { in_line_eoln, 0 }, /* %D */
-       { in_line_eoln, 0 }, /* %I */
-       { in_line_eoln, 0 }, /* %J */
+       { in_line_eoln, MDOC_JOIN }, /* %A */
+       { in_line_eoln, MDOC_JOIN }, /* %B */
+       { in_line_eoln, MDOC_JOIN }, /* %D */
+       { in_line_eoln, MDOC_JOIN }, /* %I */
+       { in_line_eoln, MDOC_JOIN }, /* %J */
        { in_line_eoln, 0 }, /* %N */
        { in_line_eoln, 0 }, /* %N */
-       { in_line_eoln, 0 }, /* %O */
+       { in_line_eoln, MDOC_JOIN }, /* %O */
        { in_line_eoln, 0 }, /* %P */
        { in_line_eoln, 0 }, /* %P */
-       { in_line_eoln, 0 }, /* %R */
-       { in_line_eoln, 0 }, /* %T */
+       { in_line_eoln, MDOC_JOIN }, /* %R */
+       { in_line_eoln, MDOC_JOIN }, /* %T */
        { in_line_eoln, 0 }, /* %V */
        { in_line_eoln, 0 }, /* %V */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ac */
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ao */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Aq */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Ac */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Ao */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Aq */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* At */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Bc */
-       { blk_full, MDOC_EXPLICIT }, /* Bf */ 
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bo */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Bq */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Bc */
+       { blk_full, MDOC_EXPLICIT }, /* Bf */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Bo */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Bq */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
        { in_line_eoln, 0 }, /* Db */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bsx */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Bx */
        { in_line_eoln, 0 }, /* Db */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Dc */
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Do */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Dq */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Ec */
-       { blk_exp_close, MDOC_EXPLICIT }, /* Ef */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Em */ 
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Dc */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Do */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Dq */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Ec */
+       { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ef */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Em */
        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Eo */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Fx */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Ms */
-       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* No */
-       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Ns */
+       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_IGNDELIM | MDOC_JOIN }, /* No */
+       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_IGNDELIM | MDOC_JOIN }, /* Ns */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Nx */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ox */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Pc */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Pc */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_IGNDELIM }, /* Pf */
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Po */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Pq */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Qc */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Ql */
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Qo */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Qq */
-       { blk_exp_close, MDOC_EXPLICIT }, /* Re */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Po */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Pq */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Qc */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ql */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Qo */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Qq */
+       { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Re */
        { blk_full, MDOC_EXPLICIT }, /* Rs */
        { blk_full, MDOC_EXPLICIT }, /* Rs */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Sc */
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* So */
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Sq */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Sc */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* So */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sq */
        { in_line_eoln, 0 }, /* Sm */
        { in_line_eoln, 0 }, /* Sm */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sx */
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Sy */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sx */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Sy */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
        { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Tn */
-       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Ux */
+       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ux */
        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
        { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Xc */
        { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Xo */
-       { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */ 
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Fc */ 
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Oo */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Oc */
+       { blk_full, MDOC_EXPLICIT | MDOC_CALLABLE }, /* Fo */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Fc */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Oo */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Oc */
        { blk_full, MDOC_EXPLICIT }, /* Bk */
        { blk_full, MDOC_EXPLICIT }, /* Bk */
-       { blk_exp_close, MDOC_EXPLICIT }, /* Ek */
+       { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ek */
        { in_line_eoln, 0 }, /* Bt */
        { in_line_eoln, 0 }, /* Hf */
        { obsolete, 0 }, /* Fr */
        { in_line_eoln, 0 }, /* Ud */
        { in_line, 0 }, /* Lb */
        { in_line_eoln, 0 }, /* Bt */
        { in_line_eoln, 0 }, /* Hf */
        { obsolete, 0 }, /* Fr */
        { in_line_eoln, 0 }, /* Ud */
        { in_line, 0 }, /* Lb */
-       { in_line_eoln, 0 }, /* Lp */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */ 
-       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */ 
-       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED }, /* Brq */
-       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED | MDOC_EXPLICIT }, /* Bro */
-       { blk_exp_close, MDOC_EXPLICIT | MDOC_CALLABLE | MDOC_PARSED }, /* Brc */
-       { in_line_eoln, 0 }, /* %C */
+       { in_line_eoln, 0 }, /* Lp */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Lk */
+       { in_line, MDOC_CALLABLE | MDOC_PARSED }, /* Mt */
+       { blk_part_imp, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Brq */
+       { blk_part_exp, MDOC_CALLABLE | MDOC_PARSED |
+                       MDOC_EXPLICIT | MDOC_JOIN }, /* Bro */
+       { blk_exp_close, MDOC_CALLABLE | MDOC_PARSED |
+                        MDOC_EXPLICIT | MDOC_JOIN }, /* Brc */
+       { in_line_eoln, MDOC_JOIN }, /* %C */
        { obsolete, 0 }, /* Es */
        { obsolete, 0 }, /* En */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
        { obsolete, 0 }, /* Es */
        { obsolete, 0 }, /* En */
        { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* Dx */
-       { in_line_eoln, 0 }, /* %Q */
+       { in_line_eoln, MDOC_JOIN }, /* %Q */
        { in_line_eoln, 0 }, /* br */
        { in_line_eoln, 0 }, /* sp */
        { in_line_eoln, 0 }, /* %U */
        { in_line_eoln, 0 }, /* br */
        { in_line_eoln, 0 }, /* sp */
        { in_line_eoln, 0 }, /* %U */
-       { phrase_ta, MDOC_CALLABLE | MDOC_PARSED }, /* Ta */
+       { phrase_ta, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ta */
 };
 
 const  struct mdoc_macro * const mdoc_macros = __mdoc_macros;
 };
 
 const  struct mdoc_macro * const mdoc_macros = __mdoc_macros;
@@ -542,6 +561,9 @@ rew_sub(enum mdoc_type t, struct mdoc *mdoc,
                case (REWIND_NONE):
                        return(1);
                case (REWIND_THIS):
                case (REWIND_NONE):
                        return(1);
                case (REWIND_THIS):
+                       n->lastline = line -
+                           (MDOC_NEWLINE & mdoc->flags &&
+                            ! (MDOC_EXPLICIT & mdoc_macros[tok].flags));
                        break;
                case (REWIND_FORCE):
                        mandoc_vmsg(MANDOCERR_SCOPEBROKEN, mdoc->parse, 
                        break;
                case (REWIND_FORCE):
                        mandoc_vmsg(MANDOCERR_SCOPEBROKEN, mdoc->parse, 
@@ -550,6 +572,8 @@ rew_sub(enum mdoc_type t, struct mdoc *mdoc,
                                        mdoc_macronames[n->tok]);
                        /* FALLTHROUGH */
                case (REWIND_MORE):
                                        mdoc_macronames[n->tok]);
                        /* FALLTHROUGH */
                case (REWIND_MORE):
+                       n->lastline = line -
+                           (MDOC_NEWLINE & mdoc->flags ? 1 : 0);
                        n = n->parent;
                        continue;
                case (REWIND_LATER):
                        n = n->parent;
                        continue;
                case (REWIND_LATER):
@@ -588,13 +612,21 @@ rew_sub(enum mdoc_type t, struct mdoc *mdoc,
  * Punctuation consists of those tokens found in mdoc_isdelim().
  */
 static int
  * Punctuation consists of those tokens found in mdoc_isdelim().
  */
 static int
-dword(struct mdoc *mdoc, int line, 
-               int col, const char *p, enum mdelim d)
+dword(struct mdoc *mdoc, int line, int col, const char *p,
+               enum mdelim d, int may_append)
 {
        
        if (DELIM_MAX == d)
                d = mdoc_isdelim(p);
 
 {
        
        if (DELIM_MAX == d)
                d = mdoc_isdelim(p);
 
+       if (may_append &&
+           ! ((MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF) & mdoc->flags) &&
+           DELIM_NONE == d && MDOC_TEXT == mdoc->last->type &&
+           DELIM_NONE == mdoc_isdelim(mdoc->last->string)) {
+               mdoc_word_append(mdoc, p);
+               return(1);
+       }
+
        if ( ! mdoc_word_alloc(mdoc, line, col, p))
                return(0);
 
        if ( ! mdoc_word_alloc(mdoc, line, col, p))
                return(0);
 
@@ -638,7 +670,7 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
                else if (ARGS_EOLN == ac)
                        break;
 
                else if (ARGS_EOLN == ac)
                        break;
 
-               dword(mdoc, line, la, p, DELIM_MAX);
+               dword(mdoc, line, la, p, DELIM_MAX, 1);
 
                /*
                 * If we encounter end-of-sentence symbols, then trigger
 
                /*
                 * If we encounter end-of-sentence symbols, then trigger
@@ -680,6 +712,8 @@ blk_exp_close(MACRO_PROT_ARGS)
        case (MDOC_Ec):
                maxargs = 1;
                break;
        case (MDOC_Ec):
                maxargs = 1;
                break;
+       case (MDOC_Ek):
+               mdoc->flags &= ~MDOC_KEEP;
        default:
                maxargs = 0;
                break;
        default:
                maxargs = 0;
                break;
@@ -782,7 +816,8 @@ blk_exp_close(MACRO_PROT_ARGS)
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, lastarg, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, lastarg, p, DELIM_MAX,
+                           MDOC_JOIN & mdoc_macros[tok].flags))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -948,7 +983,8 @@ in_line(MACRO_PROT_ARGS)
                if (DELIM_NONE == d)
                        cnt++;
 
                if (DELIM_NONE == d)
                        cnt++;
 
-               if ( ! dword(mdoc, line, la, p, d))
+               if ( ! dword(mdoc, line, la, p, d,
+                   MDOC_JOIN & mdoc_macros[tok].flags))
                        return(0);
 
                /*
                        return(0);
 
                /*
@@ -1067,7 +1103,10 @@ blk_full(MACRO_PROT_ARGS)
                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                        return(0);
                body = mdoc->last;
                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                        return(0);
                body = mdoc->last;
-       } 
+       }
+
+       if (MDOC_Bk == tok)
+               mdoc->flags |= MDOC_KEEP;
 
        ac = ARGS_ERROR;
 
 
        ac = ARGS_ERROR;
 
@@ -1112,7 +1151,7 @@ blk_full(MACRO_PROT_ARGS)
                                ARGS_PPHRASE != ac &&
                                ARGS_QWORD != ac &&
                                DELIM_OPEN == mdoc_isdelim(p)) {
                                ARGS_PPHRASE != ac &&
                                ARGS_QWORD != ac &&
                                DELIM_OPEN == mdoc_isdelim(p)) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN))
+                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -1165,7 +1204,8 @@ blk_full(MACRO_PROT_ARGS)
                        MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
                        MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+                           MDOC_JOIN & mdoc_macros[tok].flags))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -1276,10 +1316,10 @@ blk_part_imp(MACRO_PROT_ARGS)
 
                if (NULL == body && ARGS_QWORD != ac &&
                                DELIM_OPEN == mdoc_isdelim(p)) {
 
                if (NULL == body && ARGS_QWORD != ac &&
                                DELIM_OPEN == mdoc_isdelim(p)) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN))
+                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
                                return(0);
                        continue;
                                return(0);
                        continue;
-               } 
+               }
 
                if (NULL == body) {
                       if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
 
                if (NULL == body) {
                       if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
@@ -1290,7 +1330,8 @@ blk_part_imp(MACRO_PROT_ARGS)
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+                           MDOC_JOIN & mdoc_macros[tok].flags))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -1416,10 +1457,10 @@ blk_part_exp(MACRO_PROT_ARGS)
                if (NULL == head && ARGS_QWORD != ac &&
                                DELIM_OPEN == mdoc_isdelim(p)) {
                        assert(NULL == body);
                if (NULL == head && ARGS_QWORD != ac &&
                                DELIM_OPEN == mdoc_isdelim(p)) {
                        assert(NULL == body);
-                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN))
+                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
                                return(0);
                        continue;
                                return(0);
                        continue;
-               } 
+               }
 
                if (NULL == head) {
                        assert(NULL == body);
 
                if (NULL == head) {
                        assert(NULL == body);
@@ -1437,7 +1478,7 @@ blk_part_exp(MACRO_PROT_ARGS)
                        assert(head);
                        /* No check whether it's a macro! */
                        if (MDOC_Eo == tok)
                        assert(head);
                        /* No check whether it's a macro! */
                        if (MDOC_Eo == tok)
-                               if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                               if ( ! dword(mdoc, line, la, p, DELIM_MAX, 0))
                                        return(0);
 
                        if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
                                        return(0);
 
                        if ( ! rew_sub(MDOC_HEAD, mdoc, tok, line, ppos))
@@ -1455,7 +1496,8 @@ blk_part_exp(MACRO_PROT_ARGS)
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+                           MDOC_JOIN & mdoc_macros[tok].flags))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -1559,7 +1601,7 @@ in_line_argn(MACRO_PROT_ARGS)
                if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 
                                ARGS_QWORD != ac && 0 == j && 
                                DELIM_OPEN == mdoc_isdelim(p)) {
                if ( ! (MDOC_IGNDELIM & mdoc_macros[tok].flags) && 
                                ARGS_QWORD != ac && 0 == j && 
                                DELIM_OPEN == mdoc_isdelim(p)) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN))
+                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
                                return(0);
                        continue;
                } else if (0 == j)
                                return(0);
                        continue;
                } else if (0 == j)
@@ -1593,7 +1635,8 @@ in_line_argn(MACRO_PROT_ARGS)
                        flushed = 1;
                }
 
                        flushed = 1;
                }
 
-               if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+               if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+                   MDOC_JOIN & mdoc_macros[tok].flags))
                        return(0);
                j++;
        }
                        return(0);
                j++;
        }
@@ -1664,7 +1707,8 @@ in_line_eoln(MACRO_PROT_ARGS)
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup(tok, p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+                           MDOC_JOIN & mdoc_macros[tok].flags))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -1744,7 +1788,7 @@ phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
 
                if (MDOC_MAX == ntok) {
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, la, p, DELIM_MAX, 1))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
@@ -1795,7 +1839,8 @@ phrase_ta(MACRO_PROT_ARGS)
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
 
                if (MDOC_MAX == ntok) {
                ntok = ARGS_QWORD == ac ? MDOC_MAX : lookup_raw(p);
 
                if (MDOC_MAX == ntok) {
-                       if ( ! dword(mdoc, line, la, p, DELIM_MAX))
+                       if ( ! dword(mdoc, line, la, p, DELIM_MAX,
+                           MDOC_JOIN & mdoc_macros[tok].flags))
                                return(0);
                        continue;
                }
                                return(0);
                        continue;
                }
index 336791d..6ee8b3a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_man.c,v 1.52 2013/09/15 18:48:31 schwarze Exp $ */
+/*     $Id: mdoc_man.c,v 1.57 2013/12/25 22:00:45 schwarze Exp $ */
 /*
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
  *
 /*
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
  *
@@ -256,6 +256,7 @@ static      int             outflags;
 #define        MMAN_An_split   (1 << 9)  /* author mode is "split" */
 #define        MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
 #define        MMAN_PD         (1 << 11) /* inter-paragraph spacing disabled */
 #define        MMAN_An_split   (1 << 9)  /* author mode is "split" */
 #define        MMAN_An_nosplit (1 << 10) /* author mode is "nosplit" */
 #define        MMAN_PD         (1 << 11) /* inter-paragraph spacing disabled */
+#define        MMAN_nbrword    (1 << 12) /* do not break the next word */
 
 #define        BL_STACK_MAX    32
 
 
 #define        BL_STACK_MAX    32
 
@@ -364,6 +365,12 @@ print_word(const char *s)
                case (ASCII_HYPH):
                        putchar('-');
                        break;
                case (ASCII_HYPH):
                        putchar('-');
                        break;
+               case (' '):
+                       if (MMAN_nbrword & outflags) {
+                               printf("\\ ");
+                               break;
+                       }
+                       /* FALLTHROUGH */
                default:
                        putchar((unsigned char)*s);
                        break;
                default:
                        putchar((unsigned char)*s);
                        break;
@@ -371,6 +378,7 @@ print_word(const char *s)
                if (TPremain)
                        TPremain--;
        }
                if (TPremain)
                        TPremain--;
        }
+       outflags &= ~MMAN_nbrword;
 }
 
 static void
 }
 
 static void
@@ -442,7 +450,7 @@ print_offs(const char *v)
        if (Bl_stack_len)
                sz += Bl_stack[Bl_stack_len - 1];
 
        if (Bl_stack_len)
                sz += Bl_stack[Bl_stack_len - 1];
 
-       snprintf(buf, sizeof(buf), "%ldn", sz);
+       snprintf(buf, sizeof(buf), "%zun", sz);
        print_word(buf);
        outflags |= MMAN_nl;
 }
        print_word(buf);
        outflags |= MMAN_nl;
 }
@@ -495,7 +503,7 @@ print_width(const char *v, const struct mdoc_node *child, size_t defsz)
                remain = sz + 2;
        }
        if (numeric) {
                remain = sz + 2;
        }
        if (numeric) {
-               snprintf(buf, sizeof(buf), "%ldn", sz + 2);
+               snprintf(buf, sizeof(buf), "%zun", sz + 2);
                print_word(buf);
        } else
                print_word(v);
                print_word(buf);
        } else
                print_word(v);
@@ -705,24 +713,12 @@ static int
 pre_sect(DECL_ARGS)
 {
 
 pre_sect(DECL_ARGS)
 {
 
-       switch (n->type) {
-       case (MDOC_HEAD):
+       if (MDOC_HEAD == n->type) {
                outflags |= MMAN_sp;
                print_block(manacts[n->tok].prefix, 0);
                print_word("");
                putchar('\"');
                outflags &= ~MMAN_spc;
                outflags |= MMAN_sp;
                print_block(manacts[n->tok].prefix, 0);
                print_word("");
                putchar('\"');
                outflags &= ~MMAN_spc;
-               break;
-       case (MDOC_BODY):
-               if (MDOC_Sh == n->tok) {
-                       if (MDOC_SYNPRETTY & n->flags)
-                               outflags |= MMAN_Bk;
-                       else
-                               outflags &= ~MMAN_Bk;
-               }
-               break;
-       default:
-               break;
        }
        return(1);
 }
        }
        return(1);
 }
@@ -900,7 +896,7 @@ static void
 post_bk(DECL_ARGS)
 {
 
 post_bk(DECL_ARGS)
 {
 
-       if (MDOC_BODY == n->type && ! (MDOC_SYNPRETTY & n->flags))
+       if (MDOC_BODY == n->type)
                outflags &= ~MMAN_Bk;
 }
 
                outflags &= ~MMAN_Bk;
 }
 
@@ -1034,12 +1030,17 @@ post_eo(DECL_ARGS)
 static int
 pre_fa(DECL_ARGS)
 {
 static int
 pre_fa(DECL_ARGS)
 {
+       int      am_Fa;
 
 
-       if (MDOC_Fa == n->tok)
+       am_Fa = MDOC_Fa == n->tok;
+
+       if (am_Fa)
                n = n->child;
 
        while (NULL != n) {
                font_push('I');
                n = n->child;
 
        while (NULL != n) {
                font_push('I');
+               if (am_Fa || MDOC_SYNPRETTY & n->flags)
+                       outflags |= MMAN_nbrword;
                print_node(meta, n);
                font_pop();
                if (NULL != (n = n->next))
                print_node(meta, n);
                font_pop();
                if (NULL != (n = n->next))
@@ -1103,6 +1104,9 @@ pre_fn(DECL_ARGS)
        if (NULL == n)
                return(0);
 
        if (NULL == n)
                return(0);
 
+       if (MDOC_SYNPRETTY & n->flags)
+               print_block(".HP 4n", MMAN_nl);
+
        font_push('B');
        print_node(meta, n);
        font_pop();
        font_push('B');
        print_node(meta, n);
        font_pop();
@@ -1123,7 +1127,7 @@ post_fn(DECL_ARGS)
        print_word(")");
        if (MDOC_SYNPRETTY & n->flags) {
                print_word(";");
        print_word(")");
        if (MDOC_SYNPRETTY & n->flags) {
                print_word(";");
-               outflags |= MMAN_br;
+               outflags |= MMAN_PP;
        }
 }
 
        }
 }
 
@@ -1136,6 +1140,8 @@ pre_fo(DECL_ARGS)
                pre_syn(n);
                break;
        case (MDOC_HEAD):
                pre_syn(n);
                break;
        case (MDOC_HEAD):
+               if (MDOC_SYNPRETTY & n->flags)
+                       print_block(".HP 4n", MMAN_nl);
                font_push('B');
                break;
        case (MDOC_BODY):
                font_push('B');
                break;
        case (MDOC_BODY):
@@ -1148,7 +1154,7 @@ pre_fo(DECL_ARGS)
        }
        return(1);
 }
        }
        return(1);
 }
-               
+
 static void
 post_fo(DECL_ARGS)
 {
 static void
 post_fo(DECL_ARGS)
 {
@@ -1294,7 +1300,7 @@ mid_it(void)
 
        /* Restore the indentation of the enclosing list. */
        print_line(".RS", MMAN_Bk_susp);
 
        /* Restore the indentation of the enclosing list. */
        print_line(".RS", MMAN_Bk_susp);
-       snprintf(buf, sizeof(buf), "%ldn", Bl_stack[Bl_stack_len - 1]);
+       snprintf(buf, sizeof(buf), "%zun", Bl_stack[Bl_stack_len - 1]);
        print_word(buf);
 
        /* Remeber to close out this .RS block later. */
        print_word(buf);
 
        /* Remeber to close out this .RS block later. */
@@ -1408,8 +1414,10 @@ pre_nm(DECL_ARGS)
 {
        char    *name;
 
 {
        char    *name;
 
-       if (MDOC_BLOCK == n->type)
+       if (MDOC_BLOCK == n->type) {
+               outflags |= MMAN_Bk;
                pre_syn(n);
                pre_syn(n);
+       }
        if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
                return(1);
        name = n->child ? n->child->string : meta->name;
        if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
                return(1);
        name = n->child ? n->child->string : meta->name;
@@ -1419,7 +1427,7 @@ pre_nm(DECL_ARGS)
                if (NULL == n->parent->prev)
                        outflags |= MMAN_sp;
                print_block(".HP", 0);
                if (NULL == n->parent->prev)
                        outflags |= MMAN_sp;
                print_block(".HP", 0);
-               printf(" %ldn", strlen(name) + 1);
+               printf(" %zun", strlen(name) + 1);
                outflags |= MMAN_nl;
        }
        font_push('B');
                outflags |= MMAN_nl;
        }
        font_push('B');
@@ -1432,9 +1440,18 @@ static void
 post_nm(DECL_ARGS)
 {
 
 post_nm(DECL_ARGS)
 {
 
-       if (MDOC_ELEM != n->type && MDOC_HEAD != n->type)
-               return;
-       font_pop();
+       switch (n->type) {
+       case (MDOC_BLOCK):
+               outflags &= ~MMAN_Bk;
+               break;
+       case (MDOC_HEAD):
+               /* FALLTHROUGH */
+       case (MDOC_ELEM):
+               font_pop();
+               break;
+       default:
+               break;
+       }
 }
 
 static int
 }
 
 static int
index 99c5953..268fcae 100644 (file)
@@ -1,7 +1,8 @@
-/*     $Id: mdoc_term.c,v 1.249 2013/06/02 18:16:57 schwarze Exp $ */
+/*     $Id: mdoc_term.c,v 1.258 2013/12/25 21:24:12 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -100,7 +101,6 @@ static      int       termp_fl_pre(DECL_ARGS);
 static int       termp_fn_pre(DECL_ARGS);
 static int       termp_fo_pre(DECL_ARGS);
 static int       termp_ft_pre(DECL_ARGS);
 static int       termp_fn_pre(DECL_ARGS);
 static int       termp_fo_pre(DECL_ARGS);
 static int       termp_ft_pre(DECL_ARGS);
-static int       termp_igndelim_pre(DECL_ARGS);
 static int       termp_in_pre(DECL_ARGS);
 static int       termp_it_pre(DECL_ARGS);
 static int       termp_li_pre(DECL_ARGS);
 static int       termp_in_pre(DECL_ARGS);
 static int       termp_it_pre(DECL_ARGS);
 static int       termp_li_pre(DECL_ARGS);
@@ -194,12 +194,12 @@ static    const struct termact termacts[MDOC_MAX] = {
        { termp_quote_pre, termp_quote_post }, /* Eo */
        { termp_xx_pre, NULL }, /* Fx */
        { termp_bold_pre, NULL }, /* Ms */
        { termp_quote_pre, termp_quote_post }, /* Eo */
        { termp_xx_pre, NULL }, /* Fx */
        { termp_bold_pre, NULL }, /* Ms */
-       { termp_igndelim_pre, NULL }, /* No */
+       { NULL, NULL }, /* No */
        { termp_ns_pre, NULL }, /* Ns */
        { termp_xx_pre, NULL }, /* Nx */
        { termp_xx_pre, NULL }, /* Ox */
        { NULL, NULL }, /* Pc */
        { termp_ns_pre, NULL }, /* Ns */
        { termp_xx_pre, NULL }, /* Nx */
        { termp_xx_pre, NULL }, /* Ox */
        { NULL, NULL }, /* Pc */
-       { termp_igndelim_pre, termp_pf_post }, /* Pf */
+       { NULL, termp_pf_post }, /* Pf */
        { termp_quote_pre, termp_quote_post }, /* Po */
        { termp_quote_pre, termp_quote_post }, /* Pq */
        { NULL, NULL }, /* Qc */
        { termp_quote_pre, termp_quote_post }, /* Po */
        { termp_quote_pre, termp_quote_post }, /* Pq */
        { NULL, NULL }, /* Qc */
@@ -307,13 +307,10 @@ print_mdoc_node(DECL_ARGS)
        /*
         * Keeps only work until the end of a line.  If a keep was
         * invoked in a prior line, revert it to PREKEEP.
        /*
         * Keeps only work until the end of a line.  If a keep was
         * invoked in a prior line, revert it to PREKEEP.
-        *
-        * Also let SYNPRETTY sections behave as if they were wrapped
-        * in a `Bk' block.
         */
 
         */
 
-       if (TERMP_KEEP & p->flags || MDOC_SYNPRETTY & n->flags) {
-               if (n->prev ? (n->prev->line != n->line) :
+       if (TERMP_KEEP & p->flags) {
+               if (n->prev ? (n->prev->lastline != n->line) :
                    (n->parent && n->parent->line != n->line)) {
                        p->flags &= ~TERMP_KEEP;
                        p->flags |= TERMP_PREKEEP;
                    (n->parent && n->parent->line != n->line)) {
                        p->flags &= ~TERMP_KEEP;
                        p->flags |= TERMP_PREKEEP;
@@ -321,16 +318,6 @@ print_mdoc_node(DECL_ARGS)
        }
 
        /*
        }
 
        /*
-        * Since SYNPRETTY sections aren't "turned off" with `Ek',
-        * we have to intuit whether we should disable formatting.
-        */
-
-       if ( ! (MDOC_SYNPRETTY & n->flags) &&
-           ((n->prev   && MDOC_SYNPRETTY & n->prev->flags) ||
-            (n->parent && MDOC_SYNPRETTY & n->parent->flags)))
-               p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
-
-       /*
         * After the keep flags have been set up, we may now
         * produce output.  Note that some pre-handlers do so.
         */
         * After the keep flags have been set up, we may now
         * produce output.  Note that some pre-handlers do so.
         */
@@ -424,6 +411,7 @@ print_mdoc_foot(struct termp *p, const void *arg)
        p->offset = 0;
        p->rmargin = (p->maxrmargin - 
                        term_strlen(p, meta->date) + term_len(p, 1)) / 2;
        p->offset = 0;
        p->rmargin = (p->maxrmargin - 
                        term_strlen(p, meta->date) + term_len(p, 1)) / 2;
+       p->trailspace = 1;
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
 
        term_word(p, meta->os);
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
 
        term_word(p, meta->os);
@@ -438,6 +426,7 @@ print_mdoc_foot(struct termp *p, const void *arg)
 
        p->offset = p->rmargin;
        p->rmargin = p->maxrmargin;
 
        p->offset = p->rmargin;
        p->rmargin = p->maxrmargin;
+       p->trailspace = 0;
        p->flags &= ~TERMP_NOBREAK;
        p->flags |= TERMP_NOSPACE;
 
        p->flags &= ~TERMP_NOBREAK;
        p->flags |= TERMP_NOSPACE;
 
@@ -489,6 +478,7 @@ print_mdoc_head(struct termp *p, const void *arg)
        titlen = term_strlen(p, title);
 
        p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
        titlen = term_strlen(p, title);
 
        p->flags |= TERMP_NOBREAK | TERMP_NOSPACE;
+       p->trailspace = 1;
        p->offset = 0;
        p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
            (p->maxrmargin -
        p->offset = 0;
        p->rmargin = 2 * (titlen+1) + buflen < p->maxrmargin ?
            (p->maxrmargin -
@@ -507,6 +497,7 @@ print_mdoc_head(struct termp *p, const void *arg)
        term_flushln(p);
 
        p->flags &= ~TERMP_NOBREAK;
        term_flushln(p);
 
        p->flags &= ~TERMP_NOBREAK;
+       p->trailspace = 0;
        if (p->rmargin + titlen <= p->maxrmargin) {
                p->flags |= TERMP_NOSPACE;
                p->offset = p->rmargin;
        if (p->rmargin + titlen <= p->maxrmargin) {
                p->flags |= TERMP_NOSPACE;
                p->offset = p->rmargin;
@@ -794,13 +785,13 @@ termp_it_pre(DECL_ARGS)
        case (LIST_dash):
                /* FALLTHROUGH */
        case (LIST_hyphen):
        case (LIST_dash):
                /* FALLTHROUGH */
        case (LIST_hyphen):
-               if (MDOC_HEAD == n->type)
-                       p->flags |= TERMP_NOBREAK;
+               if (MDOC_HEAD != n->type)
+                       break;
+               p->flags |= TERMP_NOBREAK;
+               p->trailspace = 1;
                break;
        case (LIST_hang):
                break;
        case (LIST_hang):
-               if (MDOC_HEAD == n->type)
-                       p->flags |= TERMP_NOBREAK;
-               else
+               if (MDOC_HEAD != n->type)
                        break;
 
                /*
                        break;
 
                /*
@@ -812,16 +803,18 @@ termp_it_pre(DECL_ARGS)
                if (n->next->child && 
                                (MDOC_Bl == n->next->child->tok ||
                                 MDOC_Bd == n->next->child->tok))
                if (n->next->child && 
                                (MDOC_Bl == n->next->child->tok ||
                                 MDOC_Bd == n->next->child->tok))
-                       p->flags &= ~TERMP_NOBREAK;
-               else
-                       p->flags |= TERMP_HANG;
+                       break;
+
+               p->flags |= TERMP_NOBREAK | TERMP_HANG;
+               p->trailspace = 1;
                break;
        case (LIST_tag):
                break;
        case (LIST_tag):
-               if (MDOC_HEAD == n->type)
-                       p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
-
                if (MDOC_HEAD != n->type)
                        break;
                if (MDOC_HEAD != n->type)
                        break;
+
+               p->flags |= TERMP_NOBREAK;
+               p->trailspace = 2;
+
                if (NULL == n->next || NULL == n->next->child)
                        p->flags |= TERMP_DANGLE;
                break;
                if (NULL == n->next || NULL == n->next->child)
                        p->flags |= TERMP_DANGLE;
                break;
@@ -829,15 +822,20 @@ termp_it_pre(DECL_ARGS)
                if (MDOC_HEAD == n->type)
                        break;
 
                if (MDOC_HEAD == n->type)
                        break;
 
-               if (NULL == n->next)
+               if (NULL == n->next) {
                        p->flags &= ~TERMP_NOBREAK;
                        p->flags &= ~TERMP_NOBREAK;
-               else
+                       p->trailspace = 0;
+               } else {
                        p->flags |= TERMP_NOBREAK;
                        p->flags |= TERMP_NOBREAK;
+                       p->trailspace = 1;
+               }
 
                break;
        case (LIST_diag):
 
                break;
        case (LIST_diag):
-               if (MDOC_HEAD == n->type)
-                       p->flags |= TERMP_NOBREAK;
+               if (MDOC_HEAD != n->type)
+                       break;
+               p->flags |= TERMP_NOBREAK;
+               p->trailspace = 1;
                break;
        default:
                break;
                break;
        default:
                break;
@@ -989,8 +987,8 @@ termp_it_post(DECL_ARGS)
 
        p->flags &= ~TERMP_DANGLE;
        p->flags &= ~TERMP_NOBREAK;
 
        p->flags &= ~TERMP_DANGLE;
        p->flags &= ~TERMP_NOBREAK;
-       p->flags &= ~TERMP_TWOSPACE;
        p->flags &= ~TERMP_HANG;
        p->flags &= ~TERMP_HANG;
+       p->trailspace = 0;
 }
 
 
 }
 
 
@@ -999,8 +997,10 @@ static int
 termp_nm_pre(DECL_ARGS)
 {
 
 termp_nm_pre(DECL_ARGS)
 {
 
-       if (MDOC_BLOCK == n->type)
+       if (MDOC_BLOCK == n->type) {
+               p->flags |= TERMP_PREKEEP;
                return(1);
                return(1);
+       }
 
        if (MDOC_BODY == n->type) {
                if (NULL == n->child)
 
        if (MDOC_BODY == n->type) {
                if (NULL == n->child)
@@ -1023,6 +1023,7 @@ termp_nm_pre(DECL_ARGS)
 
        if (MDOC_HEAD == n->type && n->next->child) {
                p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
 
        if (MDOC_HEAD == n->type && n->next->child) {
                p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
+               p->trailspace = 1;
                p->rmargin = p->offset + term_len(p, 1);
                if (NULL == n->child) {
                        p->rmargin += term_strlen(p, meta->name);
                p->rmargin = p->offset + term_len(p, 1);
                if (NULL == n->child) {
                        p->rmargin += term_strlen(p, meta->name);
@@ -1048,9 +1049,12 @@ static void
 termp_nm_post(DECL_ARGS)
 {
 
 termp_nm_post(DECL_ARGS)
 {
 
-       if (MDOC_HEAD == n->type && n->next->child) {
+       if (MDOC_BLOCK == n->type) {
+               p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
+       } else if (MDOC_HEAD == n->type && n->next->child) {
                term_flushln(p);
                p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
                term_flushln(p);
                p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+               p->trailspace = 0;
        } else if (MDOC_BODY == n->type && n->child)
                term_flushln(p);
 }
        } else if (MDOC_BODY == n->type && n->child)
                term_flushln(p);
 }
@@ -1525,6 +1529,7 @@ termp_ft_pre(DECL_ARGS)
 static int
 termp_fn_pre(DECL_ARGS)
 {
 static int
 termp_fn_pre(DECL_ARGS)
 {
+       size_t           rmargin = 0;
        int              pretty;
 
        pretty = MDOC_SYNPRETTY & n->flags;
        int              pretty;
 
        pretty = MDOC_SYNPRETTY & n->flags;
@@ -1534,11 +1539,24 @@ termp_fn_pre(DECL_ARGS)
        if (NULL == (n = n->child))
                return(0);
 
        if (NULL == (n = n->child))
                return(0);
 
+       if (pretty) {
+               rmargin = p->rmargin;
+               p->rmargin = p->offset + term_len(p, 4);
+               p->flags |= TERMP_NOBREAK | TERMP_HANG;
+       }
+
        assert(MDOC_TEXT == n->type);
        term_fontpush(p, TERMFONT_BOLD);
        term_word(p, n->string);
        term_fontpop(p);
 
        assert(MDOC_TEXT == n->type);
        term_fontpush(p, TERMFONT_BOLD);
        term_word(p, n->string);
        term_fontpop(p);
 
+       if (pretty) {
+               term_flushln(p);
+               p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+               p->offset = p->rmargin;
+               p->rmargin = rmargin;
+       }
+
        p->flags |= TERMP_NOSPACE;
        term_word(p, "(");
        p->flags |= TERMP_NOSPACE;
        p->flags |= TERMP_NOSPACE;
        term_word(p, "(");
        p->flags |= TERMP_NOSPACE;
@@ -1546,6 +1564,8 @@ termp_fn_pre(DECL_ARGS)
        for (n = n->next; n; n = n->next) {
                assert(MDOC_TEXT == n->type);
                term_fontpush(p, TERMFONT_UNDER);
        for (n = n->next; n; n = n->next) {
                assert(MDOC_TEXT == n->type);
                term_fontpush(p, TERMFONT_UNDER);
+               if (pretty)
+                       p->flags |= TERMP_NBRWORD;
                term_word(p, n->string);
                term_fontpop(p);
 
                term_word(p, n->string);
                term_fontpop(p);
 
@@ -1561,6 +1581,7 @@ termp_fn_pre(DECL_ARGS)
        if (pretty) {
                p->flags |= TERMP_NOSPACE;
                term_word(p, ";");
        if (pretty) {
                p->flags |= TERMP_NOSPACE;
                term_word(p, ";");
+               term_flushln(p);
        }
 
        return(0);
        }
 
        return(0);
@@ -1580,20 +1601,16 @@ termp_fa_pre(DECL_ARGS)
 
        for (nn = n->child; nn; nn = nn->next) {
                term_fontpush(p, TERMFONT_UNDER);
 
        for (nn = n->child; nn; nn = nn->next) {
                term_fontpush(p, TERMFONT_UNDER);
+               p->flags |= TERMP_NBRWORD;
                term_word(p, nn->string);
                term_fontpop(p);
 
                term_word(p, nn->string);
                term_fontpop(p);
 
-               if (nn->next) {
+               if (nn->next || (n->next && n->next->tok == MDOC_Fa)) {
                        p->flags |= TERMP_NOSPACE;
                        term_word(p, ",");
                }
        }
 
                        p->flags |= TERMP_NOSPACE;
                        term_word(p, ",");
                }
        }
 
-       if (n->child && n->next && n->next->tok == MDOC_Fa) {
-               p->flags |= TERMP_NOSPACE;
-               term_word(p, ",");
-       }
-
        return(0);
 }
 
        return(0);
 }
 
@@ -1768,16 +1785,6 @@ termp_xx_pre(DECL_ARGS)
 
 
 /* ARGSUSED */
 
 
 /* ARGSUSED */
-static int
-termp_igndelim_pre(DECL_ARGS)
-{
-
-       p->flags |= TERMP_IGNDELIM;
-       return(1);
-}
-
-
-/* ARGSUSED */
 static void
 termp_pf_post(DECL_ARGS)
 {
 static void
 termp_pf_post(DECL_ARGS)
 {
@@ -2025,16 +2032,31 @@ termp_quote_post(DECL_ARGS)
 static int
 termp_fo_pre(DECL_ARGS)
 {
 static int
 termp_fo_pre(DECL_ARGS)
 {
+       size_t           rmargin = 0;
+       int              pretty;
+
+       pretty = MDOC_SYNPRETTY & n->flags;
 
        if (MDOC_BLOCK == n->type) {
                synopsis_pre(p, n);
                return(1);
        } else if (MDOC_BODY == n->type) {
 
        if (MDOC_BLOCK == n->type) {
                synopsis_pre(p, n);
                return(1);
        } else if (MDOC_BODY == n->type) {
+               if (pretty) {
+                       rmargin = p->rmargin;
+                       p->rmargin = p->offset + term_len(p, 4);
+                       p->flags |= TERMP_NOBREAK | TERMP_HANG;
+               }
                p->flags |= TERMP_NOSPACE;
                term_word(p, "(");
                p->flags |= TERMP_NOSPACE;
                p->flags |= TERMP_NOSPACE;
                term_word(p, "(");
                p->flags |= TERMP_NOSPACE;
+               if (pretty) {
+                       term_flushln(p);
+                       p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+                       p->offset = p->rmargin;
+                       p->rmargin = rmargin;
+               }
                return(1);
                return(1);
-       } 
+       }
 
        if (NULL == n->child)
                return(0);
 
        if (NULL == n->child)
                return(0);
@@ -2062,6 +2084,7 @@ termp_fo_post(DECL_ARGS)
        if (MDOC_SYNPRETTY & n->flags) {
                p->flags |= TERMP_NOSPACE;
                term_word(p, ";");
        if (MDOC_SYNPRETTY & n->flags) {
                p->flags |= TERMP_NOSPACE;
                term_word(p, ";");
+               term_flushln(p);
        }
 }
 
        }
 }
 
@@ -2211,7 +2234,7 @@ static void
 termp_bk_post(DECL_ARGS)
 {
 
 termp_bk_post(DECL_ARGS)
 {
 
-       if (MDOC_BODY == n->type && ! (MDOC_SYNPRETTY & n->flags))
+       if (MDOC_BODY == n->type)
                p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
 }
 
                p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP);
 }
 
index 8ffc393..4cfd620 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: mdoc_validate.c,v 1.193 2013/09/16 00:25:07 schwarze Exp $ */
+/*     $Id: mdoc_validate.c,v 1.198 2013/12/15 21:23:52 schwarze Exp $ */
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv>
- * Copyright (c) 2010, 2011, 2012 Ingo Schwarze <schwarze@openbsd.org>
+ * Copyright (c) 2010, 2011, 2012, 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -19,7 +19,7 @@
 #include "config.h"
 #endif
 
 #include "config.h"
 #endif
 
-#ifndef        OSNAME
+#ifndef OSNAME
 #include <sys/utsname.h>
 #endif
 
 #include <sys/utsname.h>
 #endif
 
@@ -97,18 +97,19 @@ static      int      post_bl_block_width(POST_ARGS);
 static int      post_bl_block_tag(POST_ARGS);
 static int      post_bl_head(POST_ARGS);
 static int      post_bx(POST_ARGS);
 static int      post_bl_block_tag(POST_ARGS);
 static int      post_bl_head(POST_ARGS);
 static int      post_bx(POST_ARGS);
+static int      post_defaults(POST_ARGS);
 static int      post_dd(POST_ARGS);
 static int      post_dt(POST_ARGS);
 static int      post_dd(POST_ARGS);
 static int      post_dt(POST_ARGS);
-static int      post_defaults(POST_ARGS);
-static int      post_literal(POST_ARGS);
 static int      post_eoln(POST_ARGS);
 static int      post_eoln(POST_ARGS);
+static int      post_hyph(POST_ARGS);
+static int      post_ignpar(POST_ARGS);
 static int      post_it(POST_ARGS);
 static int      post_lb(POST_ARGS);
 static int      post_it(POST_ARGS);
 static int      post_lb(POST_ARGS);
+static int      post_literal(POST_ARGS);
 static int      post_nm(POST_ARGS);
 static int      post_ns(POST_ARGS);
 static int      post_os(POST_ARGS);
 static int      post_par(POST_ARGS);
 static int      post_nm(POST_ARGS);
 static int      post_ns(POST_ARGS);
 static int      post_os(POST_ARGS);
 static int      post_par(POST_ARGS);
-static int      post_ignpar(POST_ARGS);
 static int      post_prol(POST_ARGS);
 static int      post_root(POST_ARGS);
 static int      post_rs(POST_ARGS);
 static int      post_prol(POST_ARGS);
 static int      post_root(POST_ARGS);
 static int      post_rs(POST_ARGS);
@@ -142,28 +143,30 @@ static    v_post   posts_bx[] = { post_bx, NULL };
 static v_post   posts_bool[] = { ebool, NULL };
 static v_post   posts_eoln[] = { post_eoln, NULL };
 static v_post   posts_defaults[] = { post_defaults, NULL };
 static v_post   posts_bool[] = { ebool, NULL };
 static v_post   posts_eoln[] = { post_eoln, NULL };
 static v_post   posts_defaults[] = { post_defaults, NULL };
+static v_post   posts_d1[] = { bwarn_ge1, post_hyph, NULL };
 static v_post   posts_dd[] = { post_dd, post_prol, NULL };
 static v_post   posts_dl[] = { post_literal, bwarn_ge1, NULL };
 static v_post   posts_dt[] = { post_dt, post_prol, NULL };
 static v_post   posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
 static v_post   posts_dd[] = { post_dd, post_prol, NULL };
 static v_post   posts_dl[] = { post_literal, bwarn_ge1, NULL };
 static v_post   posts_dt[] = { post_dt, post_prol, NULL };
 static v_post   posts_fo[] = { hwarn_eq1, bwarn_ge1, NULL };
+static v_post   posts_hyph[] = { post_hyph, NULL };
+static v_post   posts_hyphtext[] = { ewarn_ge1, post_hyph, NULL };
 static v_post   posts_it[] = { post_it, NULL };
 static v_post   posts_lb[] = { post_lb, NULL };
 static v_post   posts_it[] = { post_it, NULL };
 static v_post   posts_lb[] = { post_lb, NULL };
-static v_post   posts_nd[] = { berr_ge1, NULL };
+static v_post   posts_nd[] = { berr_ge1, post_hyph, NULL };
 static v_post   posts_nm[] = { post_nm, NULL };
 static v_post   posts_notext[] = { ewarn_eq0, NULL };
 static v_post   posts_ns[] = { post_ns, NULL };
 static v_post   posts_os[] = { post_os, post_prol, NULL };
 static v_post   posts_pp[] = { post_par, ewarn_eq0, NULL };
 static v_post   posts_rs[] = { post_rs, NULL };
 static v_post   posts_nm[] = { post_nm, NULL };
 static v_post   posts_notext[] = { ewarn_eq0, NULL };
 static v_post   posts_ns[] = { post_ns, NULL };
 static v_post   posts_os[] = { post_os, post_prol, NULL };
 static v_post   posts_pp[] = { post_par, ewarn_eq0, NULL };
 static v_post   posts_rs[] = { post_rs, NULL };
-static v_post   posts_sh[] = { post_ignpar, hwarn_ge1, post_sh, NULL };
+static v_post   posts_sh[] = { post_ignpar,hwarn_ge1,post_sh,post_hyph,NULL };
 static v_post   posts_sp[] = { post_par, ewarn_le1, NULL };
 static v_post   posts_sp[] = { post_par, ewarn_le1, NULL };
-static v_post   posts_ss[] = { post_ignpar, hwarn_ge1, NULL };
+static v_post   posts_ss[] = { post_ignpar, hwarn_ge1, post_hyph, NULL };
 static v_post   posts_st[] = { post_st, NULL };
 static v_post   posts_std[] = { post_std, NULL };
 static v_post   posts_text[] = { ewarn_ge1, NULL };
 static v_post   posts_text1[] = { ewarn_eq1, NULL };
 static v_post   posts_vt[] = { post_vt, NULL };
 static v_post   posts_st[] = { post_st, NULL };
 static v_post   posts_std[] = { post_std, NULL };
 static v_post   posts_text[] = { ewarn_ge1, NULL };
 static v_post   posts_text1[] = { ewarn_eq1, NULL };
 static v_post   posts_vt[] = { post_vt, NULL };
-static v_post   posts_wline[] = { bwarn_ge1, NULL };
 static v_pre    pres_an[] = { pre_an, NULL };
 static v_pre    pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
 static v_pre    pres_bl[] = { pre_bl, pre_par, NULL };
 static v_pre    pres_an[] = { pre_an, NULL };
 static v_pre    pres_bd[] = { pre_display, pre_bd, pre_literal, pre_par, NULL };
 static v_pre    pres_bl[] = { pre_bl, pre_par, NULL };
@@ -171,8 +174,6 @@ static      v_pre    pres_d1[] = { pre_display, NULL };
 static v_pre    pres_dl[] = { pre_literal, pre_display, NULL };
 static v_pre    pres_dd[] = { pre_dd, NULL };
 static v_pre    pres_dt[] = { pre_dt, NULL };
 static v_pre    pres_dl[] = { pre_literal, pre_display, NULL };
 static v_pre    pres_dd[] = { pre_dd, NULL };
 static v_pre    pres_dt[] = { pre_dt, NULL };
-static v_pre    pres_er[] = { NULL, NULL };
-static v_pre    pres_fd[] = { NULL, NULL };
 static v_pre    pres_it[] = { pre_it, pre_par, NULL };
 static v_pre    pres_os[] = { pre_os, NULL };
 static v_pre    pres_pp[] = { pre_par, NULL };
 static v_pre    pres_it[] = { pre_it, pre_par, NULL };
 static v_pre    pres_os[] = { pre_os, NULL };
 static v_pre    pres_pp[] = { pre_par, NULL };
@@ -188,7 +189,7 @@ static      const struct valids mdoc_valids[MDOC_MAX] = {
        { pres_sh, posts_sh },                  /* Sh */ 
        { pres_ss, posts_ss },                  /* Ss */ 
        { pres_pp, posts_pp },                  /* Pp */ 
        { pres_sh, posts_sh },                  /* Sh */ 
        { pres_ss, posts_ss },                  /* Ss */ 
        { pres_pp, posts_pp },                  /* Pp */ 
-       { pres_d1, posts_wline },               /* D1 */
+       { pres_d1, posts_d1 },                  /* D1 */
        { pres_dl, posts_dl },                  /* Dl */
        { pres_bd, posts_bd },                  /* Bd */
        { NULL, NULL },                         /* Ed */
        { pres_dl, posts_dl },                  /* Dl */
        { pres_bd, posts_bd },                  /* Bd */
        { NULL, NULL },                         /* Ed */
@@ -201,11 +202,11 @@ static    const struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, NULL },                         /* Cd */ 
        { NULL, NULL },                         /* Cm */
        { NULL, NULL },                         /* Dv */ 
        { NULL, NULL },                         /* Cd */ 
        { NULL, NULL },                         /* Cm */
        { NULL, NULL },                         /* Dv */ 
-       { pres_er, NULL },                      /* Er */ 
+       { NULL, NULL },                         /* Er */ 
        { NULL, NULL },                         /* Ev */ 
        { pres_std, posts_std },                /* Ex */ 
        { NULL, NULL },                         /* Fa */ 
        { NULL, NULL },                         /* Ev */ 
        { pres_std, posts_std },                /* Ex */ 
        { NULL, NULL },                         /* Fa */ 
-       { pres_fd, posts_text },                /* Fd */
+       { NULL, posts_text },                   /* Fd */
        { NULL, NULL },                         /* Fl */
        { NULL, NULL },                         /* Fn */ 
        { NULL, NULL },                         /* Ft */ 
        { NULL, NULL },                         /* Fl */
        { NULL, NULL },                         /* Fn */ 
        { NULL, NULL },                         /* Ft */ 
@@ -223,15 +224,15 @@ static    const struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, posts_vt },                     /* Vt */ 
        { NULL, posts_text },                   /* Xr */ 
        { NULL, posts_text },                   /* %A */
        { NULL, posts_vt },                     /* Vt */ 
        { NULL, posts_text },                   /* Xr */ 
        { NULL, posts_text },                   /* %A */
-       { NULL, posts_text },                   /* %B */ /* FIXME: can be used outside Rs/Re. */
+       { NULL, posts_hyphtext },               /* %B */ /* FIXME: can be used outside Rs/Re. */
        { NULL, posts_text },                   /* %D */
        { NULL, posts_text },                   /* %I */
        { NULL, posts_text },                   /* %J */
        { NULL, posts_text },                   /* %D */
        { NULL, posts_text },                   /* %I */
        { NULL, posts_text },                   /* %J */
-       { NULL, posts_text },                   /* %N */
-       { NULL, posts_text },                   /* %O */
+       { NULL, posts_hyphtext },               /* %N */
+       { NULL, posts_hyphtext },               /* %O */
        { NULL, posts_text },                   /* %P */
        { NULL, posts_text },                   /* %P */
-       { NULL, posts_text },                   /* %R */
-       { NULL, posts_text },                   /* %T */ /* FIXME: can be used outside Rs/Re. */
+       { NULL, posts_hyphtext },               /* %R */
+       { NULL, posts_hyphtext },               /* %T */ /* FIXME: can be used outside Rs/Re. */
        { NULL, posts_text },                   /* %V */
        { NULL, NULL },                         /* Ac */
        { NULL, NULL },                         /* Ao */
        { NULL, posts_text },                   /* %V */
        { NULL, NULL },                         /* Ac */
        { NULL, NULL },                         /* Ao */
@@ -271,7 +272,7 @@ static      const struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, NULL },                         /* So */
        { NULL, NULL },                         /* Sq */
        { NULL, posts_bool },                   /* Sm */ 
        { NULL, NULL },                         /* So */
        { NULL, NULL },                         /* Sq */
        { NULL, posts_bool },                   /* Sm */ 
-       { NULL, NULL },                         /* Sx */
+       { NULL, posts_hyph },                   /* Sx */
        { NULL, NULL },                         /* Sy */
        { NULL, NULL },                         /* Tn */
        { NULL, NULL },                         /* Ux */
        { NULL, NULL },                         /* Sy */
        { NULL, NULL },                         /* Tn */
        { NULL, NULL },                         /* Ux */
@@ -888,8 +889,6 @@ pre_sh(PRE_ARGS)
 
        if (MDOC_BLOCK != n->type)
                return(1);
 
        if (MDOC_BLOCK != n->type)
                return(1);
-
-       roff_regunset(mdoc->roff, REG_nS);
        return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
 }
 
        return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
 }
 
@@ -1592,32 +1591,71 @@ post_bl_head(POST_ARGS)
 static int
 post_bl(POST_ARGS)
 {
 static int
 post_bl(POST_ARGS)
 {
-       struct mdoc_node        *n;
+       struct mdoc_node        *nparent, *nprev; /* of the Bl block */
+       struct mdoc_node        *nblock, *nbody;  /* of the Bl */
+       struct mdoc_node        *nchild, *nnext;  /* of the Bl body */
 
 
-       if (MDOC_HEAD == mdoc->last->type) 
-               return(post_bl_head(mdoc));
-       if (MDOC_BLOCK == mdoc->last->type)
+       nbody = mdoc->last;
+       switch (nbody->type) {
+       case (MDOC_BLOCK):
                return(post_bl_block(mdoc));
                return(post_bl_block(mdoc));
-       if (MDOC_BODY != mdoc->last->type)
+       case (MDOC_HEAD):
+               return(post_bl_head(mdoc));
+       case (MDOC_BODY):
+               break;
+       default:
                return(1);
                return(1);
+       }
 
 
-       for (n = mdoc->last->child; n; n = n->next) {
-               switch (n->tok) {
-               case (MDOC_Lp):
-                       /* FALLTHROUGH */
-               case (MDOC_Pp):
-                       mdoc_nmsg(mdoc, n, MANDOCERR_CHILD);
-                       /* FALLTHROUGH */
-               case (MDOC_It):
-                       /* FALLTHROUGH */
-               case (MDOC_Sm):
+       nchild = nbody->child;
+       while (NULL != nchild) {
+               if (MDOC_It == nchild->tok || MDOC_Sm == nchild->tok) {
+                       nchild = nchild->next;
                        continue;
                        continue;
-               default:
-                       break;
                }
 
                }
 
-               mdoc_nmsg(mdoc, n, MANDOCERR_SYNTCHILD);
-               return(0);
+               mdoc_nmsg(mdoc, nchild, MANDOCERR_CHILD);
+
+               /*
+                * Move the node out of the Bl block.
+                * First, collect all required node pointers.
+                */
+
+               nblock  = nbody->parent;
+               nprev   = nblock->prev;
+               nparent = nblock->parent;
+               nnext   = nchild->next;
+
+               /*
+                * Unlink this child.
+                */
+
+               assert(NULL == nchild->prev);
+               if (0 == --nbody->nchild) {
+                       nbody->child = NULL;
+                       nbody->last  = NULL;
+                       assert(NULL == nnext);
+               } else {
+                       nbody->child = nnext;
+                       nnext->prev = NULL;
+               }
+
+               /*
+                * Relink this child.
+                */
+
+               nchild->parent = nparent;
+               nchild->prev   = nprev;
+               nchild->next   = nblock;
+
+               nblock->prev = nchild;
+               nparent->nchild++;
+               if (NULL == nprev)
+                       nparent->child = nchild;
+               else
+                       nprev->next = nchild;
+
+               nchild = nnext;
        }
 
        return(1);
        }
 
        return(1);
@@ -1636,10 +1674,16 @@ ebool(struct mdoc *mdoc)
 
        assert(MDOC_TEXT == mdoc->last->child->type);
 
 
        assert(MDOC_TEXT == mdoc->last->child->type);
 
-       if (0 == strcmp(mdoc->last->child->string, "on"))
+       if (0 == strcmp(mdoc->last->child->string, "on")) {
+               if (MDOC_Sm == mdoc->last->tok)
+                       mdoc->flags &= ~MDOC_SMOFF;
                return(1);
                return(1);
-       if (0 == strcmp(mdoc->last->child->string, "off"))
+       }
+       if (0 == strcmp(mdoc->last->child->string, "off")) {
+               if (MDOC_Sm == mdoc->last->tok)
+                       mdoc->flags |= MDOC_SMOFF;
                return(1);
                return(1);
+       }
 
        mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
        return(1);
 
        mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
        return(1);
@@ -1819,6 +1863,47 @@ post_rs(POST_ARGS)
        return(1);
 }
 
        return(1);
 }
 
+/*
+ * For some arguments of some macros,
+ * convert all breakable hyphens into ASCII_HYPH.
+ */
+static int
+post_hyph(POST_ARGS)
+{
+       struct mdoc_node        *n, *nch;
+       char                    *cp;
+
+       n = mdoc->last;
+       switch (n->type) {
+       case (MDOC_HEAD):
+               if (MDOC_Sh == n->tok || MDOC_Ss == n->tok)
+                       break;
+               return(1);
+       case (MDOC_BODY):
+               if (MDOC_D1 == n->tok || MDOC_Nd == n->tok)
+                       break;
+               return(1);
+       case (MDOC_ELEM):
+               break;
+       default:
+               return(1);
+       }
+
+       for (nch = n->child; nch; nch = nch->next) {
+               if (MDOC_TEXT != nch->type)
+                       continue;
+               cp = nch->string;
+               if (3 > strnlen(cp, 3))
+                       continue;
+               while ('\0' != *(++cp))
+                       if ('-' == *cp &&
+                           isalpha((unsigned char)cp[-1]) &&
+                           isalpha((unsigned char)cp[1]))
+                               *cp = ASCII_HYPH;
+       }
+       return(1);
+}
+
 static int
 post_ns(POST_ARGS)
 {
 static int
 post_ns(POST_ARGS)
 {
@@ -1905,10 +1990,13 @@ post_sh_head(POST_ARGS)
 
        /* The SYNOPSIS gets special attention in other areas. */
 
 
        /* The SYNOPSIS gets special attention in other areas. */
 
-       if (SEC_SYNOPSIS == sec)
+       if (SEC_SYNOPSIS == sec) {
+               roff_setreg(mdoc->roff, "nS", 1, '=');
                mdoc->flags |= MDOC_SYNOPSIS;
                mdoc->flags |= MDOC_SYNOPSIS;
-       else
+       } else {
+               roff_setreg(mdoc->roff, "nS", 0, '=');
                mdoc->flags &= ~MDOC_SYNOPSIS;
                mdoc->flags &= ~MDOC_SYNOPSIS;
+       }
 
        /* Mark our last section. */
 
 
        /* Mark our last section. */
 
index 1d8c8ab..c931664 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: out.c,v 1.45 2013/05/31 21:37:17 schwarze Exp $ */
+/*     $Id: out.c,v 1.46 2013/10/05 20:30:05 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
@@ -142,7 +142,6 @@ void
 tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
 {
        const struct tbl_dat    *dp;
 tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
 {
        const struct tbl_dat    *dp;
-       const struct tbl_head   *hp;
        struct roffcol          *col;
        int                      spans;
 
        struct roffcol          *col;
        int                      spans;
 
@@ -156,8 +155,6 @@ tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
        tbl->cols = mandoc_calloc
                ((size_t)sp->opts->cols, sizeof(struct roffcol));
 
        tbl->cols = mandoc_calloc
                ((size_t)sp->opts->cols, sizeof(struct roffcol));
 
-       hp = sp->head;
-
        for ( ; sp; sp = sp->next) {
                if (TBL_SPAN_DATA != sp->pos)
                        continue;
        for ( ; sp; sp = sp->next) {
                if (TBL_SPAN_DATA != sp->pos)
                        continue;
index 7c26086..48e16dd 100644 (file)
@@ -1,7 +1,7 @@
-.\"    $Id: roff.7,v 1.42 2013/08/08 20:07:47 schwarze Exp $
+.\"    $Id: roff.7,v 1.46 2013/12/26 02:43:18 schwarze Exp $
 .\"
 .\"
-.\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
-.\" Copyright (c) 2010, 2011 Ingo Schwarze <schwarze@openbsd.org>
+.\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010, 2011, 2013 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
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: August 8 2013 $
+.Dd $Mdocdate: December 26 2013 $
 .Dt ROFF 7
 .Os
 .Sh NAME
 .Dt ROFF 7
 .Os
 .Sh NAME
@@ -32,7 +32,7 @@ and
 manual formatting languages are based on it,
 many real-world manuals use small numbers of
 .Nm
 manual formatting languages are based on it,
 many real-world manuals use small numbers of
 .Nm
-requests intermixed with their
+requests and escape sequences intermixed with their
 .Xr mdoc 7
 or
 .Xr man 7
 .Xr mdoc 7
 or
 .Xr man 7
@@ -41,8 +41,8 @@ To properly format such manuals, the
 .Xr mandoc 1
 utility supports a tiny subset of
 .Nm
 .Xr mandoc 1
 utility supports a tiny subset of
 .Nm
-requests.
-Only these requests supported by
+requests and escapes.
+Only these requests and escapes supported by
 .Xr mandoc 1
 are documented in the present manual,
 together with the basic language syntax shared by
 .Xr mandoc 1
 are documented in the present manual,
 together with the basic language syntax shared by
@@ -85,7 +85,7 @@ documents may contain only graphable 7-bit ASCII characters, the space
 character, and, in certain circumstances, the tab character.
 The backslash character
 .Sq \e
 character, and, in certain circumstances, the tab character.
 The backslash character
 .Sq \e
-indicates the start of an escape sequence for
+indicates the start of an escape sequence, used for example for
 .Sx Comments ,
 .Sx Special Characters ,
 .Sx Predefined Strings ,
 .Sx Comments ,
 .Sx Special Characters ,
 .Sx Predefined Strings ,
@@ -93,6 +93,9 @@ and
 user-defined strings defined using the
 .Sx ds
 request.
 user-defined strings defined using the
 .Sx ds
 request.
+For a listing of escape sequences, consult the
+.Sx ESCAPE SEQUENCE REFERENCE
+below.
 .Ss Comments
 Text following an escaped double-quote
 .Sq \e\(dq ,
 .Ss Comments
 Text following an escaped double-quote
 .Sq \e\(dq ,
@@ -638,6 +641,15 @@ Begin an equation block.
 See
 .Xr eqn 7
 for a description of the equation language.
 See
 .Xr eqn 7
 for a description of the equation language.
+.Ss \&fam
+Change the font family.
+This line-scoped request is intended to have one argument specifying
+the font family to be selected.
+It is a groff extension, and currently, it is ignored including its
+arguments, and the number of arguments is not checked.
+.Ss \&hw
+Specify hyphenation points in words.
+This line-scoped request is currently ignored.
 .Ss \&hy
 Set automatic hyphenation mode.
 This line-scoped request is currently ignored.
 .Ss \&hy
 Set automatic hyphenation mode.
 This line-scoped request is currently ignored.
@@ -805,19 +817,22 @@ the name of the request, macro or string to be undefined.
 Currently, it is ignored including its arguments,
 and the number of arguments is not checked.
 .Ss \&nr
 Currently, it is ignored including its arguments,
 and the number of arguments is not checked.
 .Ss \&nr
-Define a register.
+Define or change a register.
 A register is an arbitrary string value that defines some sort of state,
 which influences parsing and/or formatting.
 Its syntax is as follows:
 .Pp
 A register is an arbitrary string value that defines some sort of state,
 which influences parsing and/or formatting.
 Its syntax is as follows:
 .Pp
-.D1 Pf \. Cm \&nr Ar name Ar value
+.D1 Pf \. Cm \&nr Ar name Oo +|- Oc Ns Ar value
 .Pp
 The
 .Ar value
 may, at the moment, only be an integer.
 .Pp
 The
 .Ar value
 may, at the moment, only be an integer.
-So far, only the following register
+If it is prefixed by a sign, the register will be
+incremented or decremented instead of assigned to.
+.Pp
+The following register
 .Ar name
 .Ar name
-is recognised:
+is handled specially:
 .Bl -tag -width Ds
 .It Cm nS
 If set to a positive integer value, certain
 .Bl -tag -width Ds
 .It Cm nS
 If set to a positive integer value, certain
@@ -914,6 +929,249 @@ Begin a table, which formats input in aligned rows and columns.
 See
 .Xr tbl 7
 for a description of the tbl language.
 See
 .Xr tbl 7
 for a description of the tbl language.
+.Sh ESCAPE SEQUENCE REFERENCE
+The
+.Xr mandoc 1
+.Nm
+parser recognises the following escape sequences.
+Note that the
+.Nm
+language defines more escape sequences not implemented in
+.Xr mandoc 1 .
+In
+.Xr mdoc 7
+and
+.Xr man 7
+documents, using escape sequences is discouraged except for those
+described in the
+.Sx LANGUAGE SYNTAX
+section above.
+.Pp
+A backslash followed by any character not listed here
+simply prints that character itself.
+.Ss \e<newline>
+A backslash at the end of an input line can be used to continue the
+logical input line on the next physical input line, joining the text
+on both lines together as if it were on a single input line.
+.Ss \e<space>
+The escape sequence backslash-space
+.Pq Sq \e\ \&
+is an unpaddable space-sized non-breaking space character; see
+.Sx Whitespace .
+.Ss \e\(dq
+The rest of the input line is treated as
+.Sx Comments .
+.Ss \e%
+Hyphenation allowed at this point of the word; ignored by
+.Xr mandoc 1 .
+.Ss \e&
+Non-printing zero-width character; see
+.Sx Whitespace .
+.Ss \e\(aq
+Acute accent special character; use
+.Sq \e(aa
+instead.
+.Ss \e( Ns Ar cc
+.Sx Special Characters
+with two-letter names, see
+.Xr mandoc_char 7 .
+.Ss \e*[ Ns Ar name ]
+Interpolate the string with the
+.Ar name ;
+see
+.Sx Predefined Strings
+and
+.Sx ds .
+For short names, there are variants
+.No \e* Ns Ar c
+and
+.No \e*( Ns Ar cc .
+.Ss \e-
+Special character
+.Dq mathematical minus sign .
+.Ss \e[ Ns Ar name ]
+.Sx Special Characters
+with names of arbitrary length, see
+.Xr mandoc_char 7 .
+.Ss \e^
+One-twelfth em half-narrow space character, effectively zero-width in
+.Xr mandoc 1 .
+.Ss \e`
+Grave accent special character; use
+.Sq \e(ga
+instead.
+.Ss \e{
+Begin conditional input; see
+.Sx if .
+.Ss \e\(ba
+One-sixth em narrow space character, effectively zero-width in
+.Xr mandoc 1 .
+.Ss \e}
+End conditional input; see
+.Sx if .
+.Ss \e~
+Paddable non-breaking space character.
+.Ss \e0
+Digit width space character.
+.Ss \eA\(aq Ns Ar string Ns \(aq
+Anchor definition; ignored by
+.Xr mandoc 1 .
+.Ss \eB\(aq Ns Ar string Ns \(aq
+Test whether
+.Ar string
+is a numerical expession; ignored by
+.Xr mandoc 1 .
+.Ss \eb\(aq Ns Ar string Ns \(aq
+Bracket building function; ignored by
+.Xr mandoc 1 .
+.Ss \eC\(aq Ns Ar name Ns \(aq
+.Sx Special Characters
+with names of arbitrary length.
+.Ss \ec
+Interrupt text processing to insert requests or macros; ignored by
+.Xr mandoc 1 .
+.Ss \eD\(aq Ns Ar string Ns \(aq
+Draw graphics function; ignored by
+.Xr mandoc 1 .
+.Ss \ed
+Move down by half a line; ignored by
+.Xr mandoc 1 .
+.Ss \ee
+Backslash special character.
+.Ss \eF[ Ns Ar name ]
+Switch font family (groff extension); ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eF Ns Ar c
+and
+.No \eF( Ns Ar cc .
+.Ss \ef[ Ns Ar name ]
+Switch to the font
+.Ar name ,
+see
+.Sx Text Decoration .
+For short names, there are variants
+.No \ef Ns Ar c
+and
+.No \ef( Ns Ar cc .
+.Ss \eg[ Ns Ar name ]
+Interpolate the format of a number register; ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eg Ns Ar c
+and
+.No \eg( Ns Ar cc .
+.Ss \eH\(aq Ns Oo +|- Oc Ns Ar number Ns \(aq
+Set the height of the current font; ignored by
+.Xr mandoc 1 .
+.Ss \eh\(aq Ns Ar number Ns \(aq
+Horizontal motion; ignored by
+.Xr mandoc 1 .
+.Ss \ek[ Ns Ar name ]
+Mark horizontal input place in register; ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \ek Ns Ar c
+and
+.No \ek( Ns Ar cc .
+.Ss \eL\(aq Ns Ar number Ns Oo Ar c Oc Ns \(aq
+Vertical line drawing function; ignored by
+.Xr mandoc 1 .
+.Ss \el\(aq Ns Ar number Ns Oo Ar c Oc Ns \(aq
+Horizontal line drawing function; ignored by
+.Xr mandoc 1 .
+.Ss \eM[ Ns Ar name ]
+Set fill (background) color (groff extension); ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eM Ns Ar c
+and
+.No \eM( Ns Ar cc .
+.Ss \em[ Ns Ar name ]
+Set glyph drawing color (groff extension); ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \em Ns Ar c
+and
+.No \em( Ns Ar cc .
+.Ss \eN\(aq Ns Ar number Ns \(aq
+Character
+.Ar number
+on the current font.
+.Ss \en[ Ns Ar name ]
+Interpolate the number register
+.Ar name .
+For short names, there are variants
+.No \en Ns Ar c
+and
+.No \en( Ns Ar cc .
+.Ss \eo\(aq Ns Ar string Ns \(aq
+Overstrike
+.Ar string ;
+ignored by
+.Xr mandoc 1 .
+.Ss \eR\(aq Ns Ar name Oo +|- Oc Ns Ar number Ns \(aq
+Set number register; ignored by
+.Xr mandoc 1 .
+.Ss \eS\(aq Ns Ar number Ns \(aq
+Slant output; ignored by
+.Xr mandoc 1 .
+.Ss \es\(aq Ns Oo +|- Oc Ns Ar number Ns \(aq
+Change point size; ignored by
+.Xr mandoc 1 .
+Alternative forms
+.No \es Ns Oo +|- Oc Ns Ar n ,
+.No \es Ns Oo +|- Oc Ns \(aq Ns Ar number Ns \(aq ,
+.No \es Ns [ Oo +|- Oc Ns Ar number ] ,
+and
+.No \es Ns Oo +|- Oc Ns [ Ar number Ns ]
+are also parsed and ignored.
+.Ss \et
+Horizontal tab; ignored by
+.Xr mandoc 1 .
+.Ss \eu
+Move up by half a line; ignored by
+.Xr mandoc 1 .
+.Ss \eV[ Ns Ar name ]
+Interpolate an environment variable; ignored by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eV Ns Ar c
+and
+.No \eV( Ns Ar cc .
+.Ss \ev\(aq Ns Ar number Ns \(aq
+Vertical motion; ignored by
+.Xr mandoc 1 .
+.Ss \ew\(aq Ns Ar string Ns \(aq
+Interpolate the width of the
+.Ar string ;
+ignored by
+.Xr mandoc 1 .
+.Ss \eX\(aq Ns Ar string Ns \(aq
+Output
+.Ar string
+as device control function; ignored in nroff mode and by
+.Xr mandoc 1 .
+.Ss \ex\(aq Ns Ar number Ns \(aq
+Extra line space function; ignored by
+.Xr mandoc 1 .
+.Ss \eY[ Ns Ar name ]
+Output a string as a device control function; ignored in nroff mode and by
+.Xr mandoc 1 .
+For short names, there are variants
+.No \eY Ns Ar c
+and
+.No \eY( Ns Ar cc .
+.Ss \eZ\(aq Ns Ar string Ns \(aq
+Print
+.Ar string
+with zero width and height; ignored by
+.Xr mandoc 1 .
+.Ss \ez
+Output the next character without advancing the cursor position;
+approximated in
+.Xr mandoc 1
+by simply skipping the next character.
 .Sh COMPATIBILITY
 This section documents compatibility between mandoc and other
 .Nm
 .Sh COMPATIBILITY
 This section documents compatibility between mandoc and other
 .Nm
index 3ee8adf..42240d2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: roff.c,v 1.178 2013/07/13 12:52:07 schwarze Exp $ */
+/*     $Id: roff.c,v 1.189 2013/12/30 18:44:06 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -46,6 +46,8 @@ enum  rofft {
        ROFF_de1,
        ROFF_ds,
        ROFF_el,
        ROFF_de1,
        ROFF_ds,
        ROFF_el,
+       ROFF_fam,
+       ROFF_hw,
        ROFF_hy,
        ROFF_ie,
        ROFF_if,
        ROFF_hy,
        ROFF_ie,
        ROFF_if,
@@ -74,18 +76,8 @@ enum rofft {
 };
 
 enum   roffrule {
 };
 
 enum   roffrule {
-       ROFFRULE_ALLOW,
-       ROFFRULE_DENY
-};
-
-/*
- * A single register entity.  If "set" is zero, the value of the
- * register should be the default one, which is per-register.
- * Registers are assumed to be unsigned ints for now.
- */
-struct reg {
-       int              set; /* whether set or not */
-       unsigned int     u; /* unsigned integer */
+       ROFFRULE_DENY,
+       ROFFRULE_ALLOW
 };
 
 /*
 };
 
 /*
@@ -105,6 +97,15 @@ struct      roffkv {
        struct roffkv   *next; /* next in list */
 };
 
        struct roffkv   *next; /* next in list */
 };
 
+/*
+ * A single number register as part of a singly-linked list.
+ */
+struct roffreg {
+       struct roffstr   key;
+       int              val;
+       struct roffreg  *next;
+};
+
 struct roff {
        enum mparset     parsetype; /* requested parse type */
        struct mparse   *parse; /* parse point */
 struct roff {
        enum mparset     parsetype; /* requested parse type */
        struct mparse   *parse; /* parse point */
@@ -112,7 +113,7 @@ struct      roff {
        enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */
        char             control; /* control character */
        int              rstackpos; /* position in rstack */
        enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */
        char             control; /* control character */
        int              rstackpos; /* position in rstack */
-       struct reg       regs[REG__MAX];
+       struct roffreg  *regtab; /* number registers */
        struct roffkv   *strtab; /* user-defined strings & macros */
        struct roffkv   *xmbtab; /* multi-byte trans table (`tr') */
        struct roffstr  *xtab; /* single-byte trans table (`tr') */
        struct roffkv   *strtab; /* user-defined strings & macros */
        struct roffkv   *xmbtab; /* multi-byte trans table (`tr') */
        struct roffstr  *xtab; /* single-byte trans table (`tr') */
@@ -183,8 +184,13 @@ static     enum rofferr     roff_cond_sub(ROFF_ARGS);
 static enum rofferr     roff_ds(ROFF_ARGS);
 static enum roffrule    roff_evalcond(const char *, int *);
 static void             roff_free1(struct roff *);
 static enum rofferr     roff_ds(ROFF_ARGS);
 static enum roffrule    roff_evalcond(const char *, int *);
 static void             roff_free1(struct roff *);
+static void             roff_freereg(struct roffreg *);
 static void             roff_freestr(struct roffkv *);
 static char            *roff_getname(struct roff *, char **, int, int);
 static void             roff_freestr(struct roffkv *);
 static char            *roff_getname(struct roff *, char **, int, int);
+static int              roff_getnum(const char *, int *, int *);
+static int              roff_getop(const char *, int *, char *);
+static int              roff_getregn(const struct roff *,
+                               const char *, size_t);
 static const char      *roff_getstrn(const struct roff *, 
                                const char *, size_t);
 static enum rofferr     roff_it(ROFF_ARGS);
 static const char      *roff_getstrn(const struct roff *, 
                                const char *, size_t);
 static enum rofferr     roff_it(ROFF_ARGS);
@@ -231,6 +237,8 @@ static      struct roffmac   roffs[ROFF_MAX] = {
        { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
        { "ds", roff_ds, NULL, NULL, 0, NULL },
        { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
        { "de1", roff_block, roff_block_text, roff_block_sub, 0, NULL },
        { "ds", roff_ds, NULL, NULL, 0, NULL },
        { "el", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
+       { "fam", roff_line_ignore, NULL, NULL, 0, NULL },
+       { "hw", roff_line_ignore, NULL, NULL, 0, NULL },
        { "hy", roff_line_ignore, NULL, NULL, 0, NULL },
        { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
        { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
        { "hy", roff_line_ignore, NULL, NULL, 0, NULL },
        { "ie", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
        { "if", roff_cond, roff_cond_text, roff_cond_sub, ROFFMAC_STRUCT, NULL },
@@ -424,6 +432,10 @@ roff_free1(struct roff *r)
 
        r->strtab = r->xmbtab = NULL;
 
 
        r->strtab = r->xmbtab = NULL;
 
+       roff_freereg(r->regtab);
+
+       r->regtab = NULL;
+
        if (r->xtab)
                for (i = 0; i < 128; i++)
                        free(r->xtab[i].p);
        if (r->xtab)
                for (i = 0; i < 128; i++)
                        free(r->xtab[i].p);
@@ -440,7 +452,6 @@ roff_reset(struct roff *r)
        roff_free1(r);
 
        r->control = 0;
        roff_free1(r);
 
        r->control = 0;
-       memset(&r->regs, 0, sizeof(struct reg) * REG__MAX);
 
        for (i = 0; i < PREDEFS_MAX; i++) 
                roff_setstr(r, predefs[i].name, predefs[i].str, 0);
 
        for (i = 0; i < PREDEFS_MAX; i++) 
                roff_setstr(r, predefs[i].name, predefs[i].str, 0);
@@ -476,22 +487,23 @@ roff_alloc(enum mparset type, struct mparse *parse)
 }
 
 /*
 }
 
 /*
- * Pre-filter each and every line for reserved words (one beginning with
- * `\*', e.g., `\*(ab').  These must be handled before the actual line
- * is processed. 
- * This also checks the syntax of regular escapes.
+ * In the current line, expand user-defined strings ("\*")
+ * and references to number registers ("\n").
+ * Also check the syntax of other escape sequences.
  */
 static enum rofferr
 roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
 {
  */
 static enum rofferr
 roff_res(struct roff *r, char **bufp, size_t *szp, int ln, int pos)
 {
-       enum mandoc_esc  esc;
+       char             ubuf[12]; /* buffer to print the number */
        const char      *stesc; /* start of an escape sequence ('\\') */
        const char      *stnam; /* start of the name, after "[(*" */
        const char      *cp;    /* end of the name, e.g. before ']' */
        const char      *res;   /* the string to be substituted */
        const char      *stesc; /* start of an escape sequence ('\\') */
        const char      *stnam; /* start of the name, after "[(*" */
        const char      *cp;    /* end of the name, e.g. before ']' */
        const char      *res;   /* the string to be substituted */
-       int              i, maxl, expand_count;
-       size_t           nsz;
-       char            *n;
+       char            *nbuf;  /* new buffer to copy bufp to */
+       size_t           nsz;   /* size of the new buffer */
+       size_t           maxl;  /* expected length of the escape name */
+       size_t           naml;  /* actual length of the escape name */
+       int              expand_count;  /* to avoid infinite loops */
 
        expand_count = 0;
 
 
        expand_count = 0;
 
@@ -501,7 +513,7 @@ again:
                stesc = cp++;
 
                /*
                stesc = cp++;
 
                /*
-                * The second character must be an asterisk.
+                * The second character must be an asterisk or an n.
                 * If it isn't, skip it anyway:  It is escaped,
                 * so it can't start another escape sequence.
                 */
                 * If it isn't, skip it anyway:  It is escaped,
                 * so it can't start another escape sequence.
                 */
@@ -509,12 +521,16 @@ again:
                if ('\0' == *cp)
                        return(ROFF_CONT);
 
                if ('\0' == *cp)
                        return(ROFF_CONT);
 
-               if ('*' != *cp) {
-                       res = cp;
-                       esc = mandoc_escape(&cp, NULL, NULL);
-                       if (ESCAPE_ERROR != esc)
+               switch (*cp) {
+               case ('*'):
+                       res = NULL;
+                       break;
+               case ('n'):
+                       res = ubuf;
+                       break;
+               default:
+                       if (ESCAPE_ERROR != mandoc_escape(&cp, NULL, NULL))
                                continue;
                                continue;
-                       cp = res;
                        mandoc_msg
                                (MANDOCERR_BADESCAPE, r->parse, 
                                 ln, (int)(stesc - *bufp), NULL);
                        mandoc_msg
                                (MANDOCERR_BADESCAPE, r->parse, 
                                 ln, (int)(stesc - *bufp), NULL);
@@ -525,7 +541,7 @@ again:
 
                /*
                 * The third character decides the length
 
                /*
                 * The third character decides the length
-                * of the name of the string.
+                * of the name of the string or register.
                 * Save a pointer to the name.
                 */
 
                 * Save a pointer to the name.
                 */
 
@@ -548,7 +564,7 @@ again:
 
                /* Advance to the end of the name. */
 
 
                /* Advance to the end of the name. */
 
-               for (i = 0; 0 == maxl || i < maxl; i++, cp++) {
+               for (naml = 0; 0 == maxl || naml < maxl; naml++, cp++) {
                        if ('\0' == *cp) {
                                mandoc_msg
                                        (MANDOCERR_BADESCAPE, 
                        if ('\0' == *cp) {
                                mandoc_msg
                                        (MANDOCERR_BADESCAPE, 
@@ -565,7 +581,11 @@ again:
                 * undefined, resume searching for escapes.
                 */
 
                 * undefined, resume searching for escapes.
                 */
 
-               res = roff_getstrn(r, stnam, (size_t)i);
+               if (NULL == res)
+                       res = roff_getstrn(r, stnam, naml);
+               else
+                       snprintf(ubuf, sizeof(ubuf), "%d",
+                           roff_getregn(r, stnam, naml));
 
                if (NULL == res) {
                        mandoc_msg
 
                if (NULL == res) {
                        mandoc_msg
@@ -579,15 +599,15 @@ again:
                pos = stesc - *bufp;
 
                nsz = *szp + strlen(res) + 1;
                pos = stesc - *bufp;
 
                nsz = *szp + strlen(res) + 1;
-               n = mandoc_malloc(nsz);
+               nbuf = mandoc_malloc(nsz);
 
 
-               strlcpy(n, *bufp, (size_t)(stesc - *bufp + 1));
-               strlcat(n, res, nsz);
-               strlcat(n, cp + (maxl ? 0 : 1), nsz);
+               strlcpy(nbuf, *bufp, (size_t)(stesc - *bufp + 1));
+               strlcat(nbuf, res, nsz);
+               strlcat(nbuf, cp + (maxl ? 0 : 1), nsz);
 
                free(*bufp);
 
 
                free(*bufp);
 
-               *bufp = n;
+               *bufp = nbuf;
                *szp = nsz;
 
                if (EXPAND_LIMIT >= ++expand_count)
                *szp = nsz;
 
                if (EXPAND_LIMIT >= ++expand_count)
@@ -626,8 +646,7 @@ roff_parsetext(char **bufp, size_t *szp, int pos, int *offs)
                if ('\\' == *p) {
                        /* Skip over escapes. */
                        p++;
                if ('\\' == *p) {
                        /* Skip over escapes. */
                        p++;
-                       esc = mandoc_escape
-                               ((const char **)&p, NULL, NULL);
+                       esc = mandoc_escape((const char **)&p, NULL, NULL);
                        if (ESCAPE_ERROR == esc)
                                break;
                        continue;
                        if (ESCAPE_ERROR == esc)
                                break;
                        continue;
@@ -698,19 +717,14 @@ roff_parseln(struct roff *r, int ln, char **bufp,
                assert(ROFF_IGN == e || ROFF_CONT == e);
                if (ROFF_CONT != e)
                        return(e);
                assert(ROFF_IGN == e || ROFF_CONT == e);
                if (ROFF_CONT != e)
                        return(e);
-               if (r->eqn)
-                       return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
-               if (r->tbl)
-                       return(tbl_read(r->tbl, ln, *bufp, pos));
-               return(roff_parsetext(bufp, szp, pos, offs));
-       } else if ( ! ctl) {
-               if (r->eqn)
-                       return(eqn_read(&r->eqn, ln, *bufp, pos, offs));
+       }
+       if (r->eqn)
+               return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
+       if ( ! ctl) {
                if (r->tbl)
                        return(tbl_read(r->tbl, ln, *bufp, pos));
                return(roff_parsetext(bufp, szp, pos, offs));
                if (r->tbl)
                        return(tbl_read(r->tbl, ln, *bufp, pos));
                return(roff_parsetext(bufp, szp, pos, offs));
-       } else if (r->eqn)
-               return(eqn_read(&r->eqn, ln, *bufp, ppos, offs));
+       }
 
        /*
         * If a scope is open, go to the child handler for that macro,
 
        /*
         * If a scope is open, go to the child handler for that macro,
@@ -1116,9 +1130,61 @@ roff_cond_text(ROFF_ARGS)
        return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }
 
        return(ROFFRULE_DENY == rr ? ROFF_IGN : ROFF_CONT);
 }
 
+static int
+roff_getnum(const char *v, int *pos, int *res)
+{
+       int p, n;
+
+       p = *pos;
+       n = v[p] == '-';
+       if (n)
+               p++;
+
+       for (*res = 0; isdigit((unsigned char)v[p]); p++)
+               *res += 10 * *res + v[p] - '0';
+       if (p == *pos + n)
+               return 0;
+
+       if (n)
+               *res = -*res;
+
+       *pos = p;
+       return 1;
+}
+
+static int
+roff_getop(const char *v, int *pos, char *res)
+{
+       int e;
+
+       *res = v[*pos];
+       e = v[*pos + 1] == '=';
+
+       switch (*res) {
+       case '=':
+               break;
+       case '>':
+               if (e)
+                       *res = 'g';
+               break;
+       case '<':
+               if (e)
+                       *res = 'l';
+               break;
+       default:
+               return(0);
+       }
+
+       *pos += 1 + e;
+
+       return(*res);
+}
+
 static enum roffrule
 roff_evalcond(const char *v, int *pos)
 {
 static enum roffrule
 roff_evalcond(const char *v, int *pos)
 {
+       int      not, lh, rh;
+       char     op;
 
        switch (v[*pos]) {
        case ('n'):
 
        switch (v[*pos]) {
        case ('n'):
@@ -1131,13 +1197,47 @@ roff_evalcond(const char *v, int *pos)
        case ('t'):
                (*pos)++;
                return(ROFFRULE_DENY);
        case ('t'):
                (*pos)++;
                return(ROFFRULE_DENY);
+       case ('!'):
+               (*pos)++;
+               not = 1;
+               break;
        default:
        default:
+               not = 0;
                break;
        }
 
                break;
        }
 
-       while (v[*pos] && ' ' != v[*pos])
-               (*pos)++;
-       return(ROFFRULE_DENY);
+       if (!roff_getnum(v, pos, &lh))
+               return ROFFRULE_DENY;
+       if (!roff_getop(v, pos, &op)) {
+               if (lh < 0)
+                       lh = 0;
+               goto out;
+       }
+       if (!roff_getnum(v, pos, &rh))
+               return ROFFRULE_DENY;
+       switch (op) {
+       case 'g':
+               lh = lh >= rh;
+               break;
+       case 'l':
+               lh = lh <= rh;
+               break;
+       case '=':
+               lh = lh == rh;
+               break;
+       case '>':
+               lh = lh > rh;
+               break;
+       case '<':
+               lh = lh < rh;
+               break;
+       default:
+               return ROFFRULE_DENY;
+       }
+out:
+       if (not)
+               lh = !lh;
+       return lh ? ROFFRULE_ALLOW : ROFFRULE_DENY;
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -1258,25 +1358,71 @@ roff_ds(ROFF_ARGS)
        return(ROFF_IGN);
 }
 
        return(ROFF_IGN);
 }
 
+void
+roff_setreg(struct roff *r, const char *name, int val, char sign)
+{
+       struct roffreg  *reg;
+
+       /* Search for an existing register with the same name. */
+       reg = r->regtab;
+
+       while (reg && strcmp(name, reg->key.p))
+               reg = reg->next;
+
+       if (NULL == reg) {
+               /* Create a new register. */
+               reg = mandoc_malloc(sizeof(struct roffreg));
+               reg->key.p = mandoc_strdup(name);
+               reg->key.sz = strlen(name);
+               reg->val = 0;
+               reg->next = r->regtab;
+               r->regtab = reg;
+       }
+
+       if ('+' == sign)
+               reg->val += val;
+       else if ('-' == sign)
+               reg->val -= val;
+       else
+               reg->val = val;
+}
+
 int
 int
-roff_regisset(const struct roff *r, enum regs reg)
+roff_getreg(const struct roff *r, const char *name)
 {
 {
+       struct roffreg  *reg;
 
 
-       return(r->regs[(int)reg].set);
+       for (reg = r->regtab; reg; reg = reg->next)
+               if (0 == strcmp(name, reg->key.p))
+                       return(reg->val);
+
+       return(0);
 }
 
 }
 
-unsigned int
-roff_regget(const struct roff *r, enum regs reg)
+static int
+roff_getregn(const struct roff *r, const char *name, size_t len)
 {
 {
+       struct roffreg  *reg;
 
 
-       return(r->regs[(int)reg].u);
+       for (reg = r->regtab; reg; reg = reg->next)
+               if (len == reg->key.sz &&
+                   0 == strncmp(name, reg->key.p, len))
+                       return(reg->val);
+
+       return(0);
 }
 
 }
 
-void
-roff_regunset(struct roff *r, enum regs reg)
+static void
+roff_freereg(struct roffreg *reg)
 {
 {
+       struct roffreg  *old_reg;
 
 
-       r->regs[(int)reg].set = 0;
+       while (NULL != reg) {
+               free(reg->key.p);
+               old_reg = reg;
+               reg = reg->next;
+               free(old_reg);
+       }
 }
 
 /* ARGSUSED */
 }
 
 /* ARGSUSED */
@@ -1285,18 +1431,21 @@ roff_nr(ROFF_ARGS)
 {
        const char      *key;
        char            *val;
 {
        const char      *key;
        char            *val;
+       size_t           sz;
        int              iv;
        int              iv;
+       char             sign;
 
        val = *bufp + pos;
        key = roff_getname(r, &val, ln, pos);
 
 
        val = *bufp + pos;
        key = roff_getname(r, &val, ln, pos);
 
-       if (0 == strcmp(key, "nS")) {
-               r->regs[(int)REG_nS].set = 1;
-               if ((iv = mandoc_strntoi(val, strlen(val), 10)) >= 0)
-                       r->regs[(int)REG_nS].u = (unsigned)iv;
-               else
-                       r->regs[(int)REG_nS].u = 0u;
-       }
+       sign = *val;
+       if ('+' == sign || '-' == sign)
+               val++;
+
+       sz = strspn(val, "0123456789");
+       iv = sz ? mandoc_strntoi(val, sz, 10) : 0;
+
+       roff_setreg(r, key, iv, sign);
 
        return(ROFF_IGN);
 }
 
        return(ROFF_IGN);
 }
@@ -1583,7 +1732,7 @@ roff_userdef(ROFF_ARGS)
 
        /*
         * Collect pointers to macro argument strings
 
        /*
         * Collect pointers to macro argument strings
-        * and null-terminate them.
+        * and NUL-terminate them.
         */
        cp = *bufp + pos;
        for (i = 0; i < 9; i++)
         */
        cp = *bufp + pos;
        for (i = 0; i < 9; i++)
index bedc6a6..c52ddab 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: st.in,v 1.20 2013/06/19 21:20:27 schwarze Exp $ */
+/*     $Id: st.in,v 1.22 2013/12/25 14:09:32 schwarze Exp $ */
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 /*
  * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -71,11 +71,12 @@ LINE("-xpg4.2",             "X/Open Portability Guide Issue\\~4, Version\\~2 (\\(lqXPG4.2\\
 LINE("-xpg4.3",                "X/Open Portability Guide Issue\\~4, Version\\~3 (\\(lqXPG4.3\\(rq)")
 LINE("-xbd5",          "X/Open Base Definitions Issue\\~5 (\\(lqXBD5\\(rq)")
 LINE("-xcu5",          "X/Open Commands and Utilities Issue\\~5 (\\(lqXCU5\\(rq)")
 LINE("-xpg4.3",                "X/Open Portability Guide Issue\\~4, Version\\~3 (\\(lqXPG4.3\\(rq)")
 LINE("-xbd5",          "X/Open Base Definitions Issue\\~5 (\\(lqXBD5\\(rq)")
 LINE("-xcu5",          "X/Open Commands and Utilities Issue\\~5 (\\(lqXCU5\\(rq)")
+LINE("-xsh4.2",                "X/Open System Interfaces and Headers Issue\\~4, Version\\~2 (\\(lqXSH4.2\\(rq)")
 LINE("-xsh5",          "X/Open System Interfaces and Headers Issue\\~5 (\\(lqXSH5\\(rq)")
 LINE("-xns5",          "X/Open Networking Services Issue\\~5 (\\(lqXNS5\\(rq)")
 LINE("-xns5.2",                "X/Open Networking Services Issue\\~5.2 (\\(lqXNS5.2\\(rq)")
 LINE("-xns5.2d2.0",    "X/Open Networking Services Issue\\~5.2 Draft\\~2.0 (\\(lqXNS5.2D2.0\\(rq)")
 LINE("-xcurses4.2",    "X/Open Curses Issue\\~4, Version\\~2 (\\(lqXCURSES4.2\\(rq)")
 LINE("-xsh5",          "X/Open System Interfaces and Headers Issue\\~5 (\\(lqXSH5\\(rq)")
 LINE("-xns5",          "X/Open Networking Services Issue\\~5 (\\(lqXNS5\\(rq)")
 LINE("-xns5.2",                "X/Open Networking Services Issue\\~5.2 (\\(lqXNS5.2\\(rq)")
 LINE("-xns5.2d2.0",    "X/Open Networking Services Issue\\~5.2 Draft\\~2.0 (\\(lqXNS5.2D2.0\\(rq)")
 LINE("-xcurses4.2",    "X/Open Curses Issue\\~4, Version\\~2 (\\(lqXCURSES4.2\\(rq)")
-LINE("-susv2",         "Version\\~2 of the Single UNIX Specification")
-LINE("-susv3",         "Version\\~3 of the Single UNIX Specification")
+LINE("-susv2",         "Version\\~2 of the Single UNIX Specification (\\(lqSUSv2\\(rq)")
+LINE("-susv3",         "Version\\~3 of the Single UNIX Specification (\\(lqSUSv3\\(rq)")
 LINE("-svid4",         "System\\~V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
 LINE("-svid4",         "System\\~V Interface Definition, Fourth Edition (\\(lqSVID4\\(rq)")
index 16def78..e7b9557 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: term.c,v 1.210 2013/08/21 21:20:40 schwarze Exp $ */
+/*     $Id: term.c,v 1.214 2013/12/25 00:39:31 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010, 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -83,9 +83,8 @@ term_end(struct termp *p)
  *  - TERMP_NOBREAK: this is the most important and is used when making
  *    columns.  In short: don't print a newline and instead expect the
  *    next call to do the padding up to the start of the next column.
  *  - TERMP_NOBREAK: this is the most important and is used when making
  *    columns.  In short: don't print a newline and instead expect the
  *    next call to do the padding up to the start of the next column.
- *
- *  - TERMP_TWOSPACE: make sure there is room for at least two space
- *    characters of padding.  Otherwise, rather break the line.
+ *    p->trailspace may be set to 0, 1, or 2, depending on how many
+ *    space characters are required at the end of the column.
  *
  *  - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and
  *    the line is overrun, and don't pad-right if it's underrun.
  *
  *  - TERMP_DANGLE: don't newline when TERMP_NOBREAK is specified and
  *    the line is overrun, and don't pad-right if it's underrun.
@@ -121,7 +120,12 @@ term_flushln(struct termp *p)
         * First, establish the maximum columns of "visible" content.
         * This is usually the difference between the right-margin and
         * an indentation, but can be, for tagged lists or columns, a
         * First, establish the maximum columns of "visible" content.
         * This is usually the difference between the right-margin and
         * an indentation, but can be, for tagged lists or columns, a
-        * small set of values. 
+        * small set of values.
+        *
+        * The following unsigned-signed subtractions look strange,
+        * but they are actually correct.  If the int p->overstep
+        * is negative, it gets sign extended.  Subtracting that
+        * very large size_t effectively adds a small number to dv.
         */
        assert  (p->rmargin >= p->offset);
        dv     = p->rmargin - p->offset;
         */
        assert  (p->rmargin >= p->offset);
        dv     = p->rmargin - p->offset;
@@ -200,7 +204,11 @@ term_flushln(struct termp *p)
                        if (0 < ntab)
                                vbl += ntab * p->tabwidth;
 
                        if (0 < ntab)
                                vbl += ntab * p->tabwidth;
 
-                       /* Remove the p->overstep width. */
+                       /*
+                        * Remove the p->overstep width.
+                        * Again, if p->overstep is negative,
+                        * sign extension does the right thing.
+                        */
 
                        bp += (size_t)p->overstep;
                        p->overstep = 0;
 
                        bp += (size_t)p->overstep;
                        p->overstep = 0;
@@ -269,15 +277,17 @@ term_flushln(struct termp *p)
        }
 
        if (TERMP_HANG & p->flags) {
        }
 
        if (TERMP_HANG & p->flags) {
-               /* We need one blank after the tag. */
-               p->overstep = (int)(vis - maxvis + (*p->width)(p, ' '));
+               p->overstep = (int)(vis - maxvis +
+                               p->trailspace * (*p->width)(p, ' '));
 
                /*
                 * If we have overstepped the margin, temporarily move
                 * it to the right and flag the rest of the line to be
                 * shorter.
 
                /*
                 * If we have overstepped the margin, temporarily move
                 * it to the right and flag the rest of the line to be
                 * shorter.
+                * If there is a request to keep the columns together,
+                * allow negative overstep when the column is not full.
                 */
                 */
-               if (p->overstep < 0)
+               if (p->trailspace && p->overstep < 0)
                        p->overstep = 0;
                return;
 
                        p->overstep = 0;
                return;
 
@@ -285,8 +295,7 @@ term_flushln(struct termp *p)
                return;
 
        /* If the column was overrun, break the line. */
                return;
 
        /* If the column was overrun, break the line. */
-       if (maxvis <= vis +
-           ((TERMP_TWOSPACE & p->flags) ? (*p->width)(p, ' ') : 0)) {
+       if (maxvis < vis + p->trailspace * (*p->width)(p, ' ')) {
                (*p->endline)(p);
                p->viscol = 0;
        }
                (*p->endline)(p);
                p->viscol = 0;
        }
@@ -398,6 +407,7 @@ term_fontpop(struct termp *p)
 void
 term_word(struct termp *p, const char *word)
 {
 void
 term_word(struct termp *p, const char *word)
 {
+       const char       nbrsp[2] = { ASCII_NBRSP, 0 };
        const char      *seq, *cp;
        char             c;
        int              sz, uc;
        const char      *seq, *cp;
        char             c;
        int              sz, uc;
@@ -420,7 +430,7 @@ term_word(struct termp *p, const char *word)
        else
                p->flags |= TERMP_NOSPACE;
 
        else
                p->flags |= TERMP_NOSPACE;
 
-       p->flags &= ~(TERMP_SENTENCE | TERMP_IGNDELIM);
+       p->flags &= ~TERMP_SENTENCE;
 
        while ('\0' != *word) {
                if ('\\' != *word) {
 
        while ('\0' != *word) {
                if ('\\' != *word) {
@@ -429,7 +439,15 @@ term_word(struct termp *p, const char *word)
                                word++;
                                continue;
                        }
                                word++;
                                continue;
                        }
-                       ssz = strcspn(word, "\\");
+                       if (TERMP_NBRWORD & p->flags) {
+                               if (' ' == *word) {
+                                       encode(p, nbrsp, 1);
+                                       word++;
+                                       continue;
+                               }
+                               ssz = strcspn(word, "\\ ");
+                       } else
+                               ssz = strcspn(word, "\\");
                        encode(p, word, ssz);
                        word += (int)ssz;
                        continue;
                        encode(p, word, ssz);
                        word += (int)ssz;
                        continue;
@@ -504,6 +522,7 @@ term_word(struct termp *p, const char *word)
                        break;
                }
        }
                        break;
                }
        }
+       p->flags &= ~TERMP_NBRWORD;
 }
 
 static void
 }
 
 static void
index 6aa9934..8cad4be 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: term.h,v 1.94 2013/08/21 21:20:40 schwarze Exp $ */
+/*     $Id: term.h,v 1.97 2013/12/25 00:39:31 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2011, 2012, 2013 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
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -63,23 +64,23 @@ struct      termp {
        size_t            tabwidth;     /* Distance of tab positions. */
        size_t            col;          /* Bytes in buf. */
        size_t            viscol;       /* Chars on current line. */
        size_t            tabwidth;     /* Distance of tab positions. */
        size_t            col;          /* Bytes in buf. */
        size_t            viscol;       /* Chars on current line. */
+       size_t            trailspace;   /* See termp_flushln(). */
        int               overstep;     /* See termp_flushln(). */
        int               skipvsp;      /* Vertical space to skip. */
        int               flags;
 #define        TERMP_SENTENCE   (1 << 1)       /* Space before a sentence. */
 #define        TERMP_NOSPACE    (1 << 2)       /* No space before words. */
        int               overstep;     /* See termp_flushln(). */
        int               skipvsp;      /* Vertical space to skip. */
        int               flags;
 #define        TERMP_SENTENCE   (1 << 1)       /* Space before a sentence. */
 #define        TERMP_NOSPACE    (1 << 2)       /* No space before words. */
-#define        TERMP_NOBREAK    (1 << 4)       /* See term_flushln(). */
-#define        TERMP_IGNDELIM   (1 << 6)       /* Delims like regulars. */
-#define        TERMP_NONOSPACE  (1 << 7)       /* No space (no autounset). */
-#define        TERMP_DANGLE     (1 << 8)       /* See term_flushln(). */
-#define        TERMP_HANG       (1 << 9)       /* See term_flushln(). */
-#define        TERMP_TWOSPACE   (1 << 10)      /* See term_flushln(). */
+#define        TERMP_NONOSPACE  (1 << 3)       /* No space (no autounset). */
+#define        TERMP_NBRWORD    (1 << 4)       /* Make next word nonbreaking. */
+#define        TERMP_KEEP       (1 << 5)       /* Keep words together. */
+#define        TERMP_PREKEEP    (1 << 6)       /* ...starting with the next one. */
+#define        TERMP_SKIPCHAR   (1 << 7)       /* Skip the next character. */
+#define        TERMP_NOBREAK    (1 << 8)