mdocml: update to stable snapshot as per 12/23/13
authorFranco Fichtner <franco@lastsummer.de>
Wed, 25 Dec 2013 10:53:40 +0000 (11:53 +0100)
committerFranco Fichtner <franco@lastsummer.de>
Wed, 25 Dec 2013 13:34:00 +0000 (14:34 +0100)
Courtesy-of: Ingo Schwarze <schwarze at mdocml dot bsd dot lv>

35 files changed:
contrib/mdocml/Makefile
contrib/mdocml/NEWS
contrib/mdocml/README.DRAGONFLY
contrib/mdocml/TODO
contrib/mdocml/apropos_db.c
contrib/mdocml/catman.c
contrib/mdocml/cgi.c
contrib/mdocml/config.h
contrib/mdocml/config.h.post
contrib/mdocml/index.sgml
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_argv.c
contrib/mdocml/mdoc_macro.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/term.c
contrib/mdocml/term.h

index 044d087..39772c9 100644 (file)
@@ -31,7 +31,7 @@ STATIC                 = -static
 # 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
@@ -309,7 +309,7 @@ clean:
        rm -f catman $(CATMAN_OBJS)
        rm -f demandoc $(DEMANDOC_OBJS)
        rm -f mandoc $(MANDOC_OBJS)
-       rm -f config.h config.log $(COMPAT_OBJS)
+       rm -f config.log $(COMPAT_OBJS)
        rm -f mdocml.tar.gz
        rm -f index.html $(INDEX_OBJS)
        rm -rf *.dSYM
@@ -390,31 +390,32 @@ config.h: config.h.pre config.h.post
        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; \
-         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; \
-         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; \
-         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; \
-         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; \
-         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; \
-         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; \
index 784b89b..99e71ca 100644 (file)
@@ -1,4 +1,4 @@
-$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.
 
@@ -130,13 +130,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.
- * 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.
+ * 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
 
@@ -150,19 +153,23 @@ Changes in version 1.10.9, released on January 7, 2011
 
 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.
+ * 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
 
@@ -194,12 +201,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
- * "Bk" mdoc(7) support
  * 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
+ * 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
 
index 40a57cf..f2753d1 100644 (file)
@@ -11,11 +11,8 @@ sha1 = 6a86cc4f373bcc51aa8bf1a7499db368e977a166
 
 Local modifications applied to the following files:
        config.h
-       lib.in          (upstream sync)
+       Makefile
        msec.in
-       man_macro.c     (upstream sync)
-       mandoc.3        (upstream sync)
-       mdoc.7          (upstream sync)
-       mdoc_man.c      (upstream sync)
-       mdoc_validate.c (upstream sync)
-       st.in           (upstream sync)
+
+The source code is currently kept in sync with the stable branch of
+the upstream CVS for collaboration purposes.
index 0aebbd3..ee7bee5 100644 (file)
@@ -1,19 +1,13 @@
 ************************************************************************
 * Official mandoc TODO.
-* $Id: TODO,v 1.157 2013/09/27 21:12:34 schwarze Exp $
+* $Id: TODO,v 1.160 2013/12/15 21:30:13 schwarze Exp $
 ************************************************************************
 
 ************************************************************************
 * 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
 - .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
 
@@ -67,6 +67,9 @@
   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
 
 
 --- 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
   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
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>
 #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 <db.h>
+#elif defined(__linux__)
+# include <endian.h>
+#elif defined(__sun)
+# include <sys/byteorder.h>
 #else
 # include <sys/endian.h>
+#endif
+
+#if defined(__linux__) || defined(__sun)
+# include <db_185.h>
+#else
 # include <db.h>
 #endif
 
@@ -414,11 +419,10 @@ apropos_search(int pathsz, char **paths, const struct opts *opts,
 {
        struct rectree   tree;
        struct mchars   *mc;
-       int              i, rc;
+       int              i;
 
        memset(&tree, 0, sizeof(struct rectree));
 
-       rc = 0;
        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>
  *
@@ -31,7 +31,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun)
 # 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];
-       pid_t            pid;
-
-       pid = -1;
 
        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>
  *
 #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"
@@ -42,7 +49,7 @@
 #include "manpath.h"
 #include "mandocdb.h"
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun)
 # include <db_185.h>
 #else
 # include <db.h>
@@ -1097,11 +1104,20 @@ static int
 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)
+#endif
                        if (0 == strcmp(d->d_name, "catman.conf"))
                                return(1);
+  }
 
        return(0);
 }
@@ -1118,6 +1134,9 @@ pathgen(DIR *dir, char *path, struct req *req)
        DIR             *cd;
        int              rc;
        size_t           sz, ssz;
+#if defined(__sun)
+       struct stat      sb;
+#endif
 
        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))) {
-               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';
@@ -1182,7 +1207,13 @@ pathgen(DIR *dir, char *path, struct req *req)
 
        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';
index 235bfd1..eabe675 100644 (file)
@@ -7,13 +7,14 @@
 
 #include <stdio.h>
 
+#define VERSION "1.12.2"
+#define HAVE_FGETLN
 #define HAVE_STRPTIME
 #define HAVE_GETSUBOPT
 #define HAVE_STRLCAT
 #define HAVE_MMAP
 #define HAVE_STRLCPY
 
-#define VERSION        "1.12.2"
 #define OSNAME "DragonFly 3.7"
 
 #include <sys/types.h>
@@ -37,6 +38,9 @@
 #  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
index cee82aa..9a33671 100644 (file)
@@ -19,6 +19,9 @@
 #  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
index e716635..c645ddd 100644 (file)
@@ -7,6 +7,7 @@
        </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">
                <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>
-                       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.
-                       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.netbsd.org/">NetBSD</A>,
+                       <A CLASS="external" HREF="http://www.dragonflybsd.org/">DragonFly</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>.
                        <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
@@ -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
-                       <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">
@@ -71,7 +78,7 @@
                                <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.2 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>
@@ -86,7 +93,7 @@
                                <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.1 port)
                                        </TD>
                                </TR>
                                <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>
                                <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>
                                </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>
                        <A NAME="news">News</A>
                </H1>
                <P CLASS="news">
-                       02-10-2013: version 1.12.2
+                       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,
                        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
+                       23-03-2012: 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
                <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,
-                               $Date: 2013/10/05 14:05:09 $
+                               $Date: 2013/11/07 22:09:54 $
                        </SMALL>
                </P>
        </BODY>
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) 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
@@ -29,11 +30,6 @@ enum rofferr {
        ROFF_ERR /* badness: puke and stop */
 };
 
-enum   regs {
-       REG_nS = 0, /* nS register */
-       REG__MAX
-};
-
 __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 *);
-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 *);
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) 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
@@ -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_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 */
@@ -57,8 +60,8 @@ struct        mdoc_macro {
 #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 {
@@ -107,6 +110,7 @@ __BEGIN_DECLS
 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, 
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>
  *
@@ -40,7 +40,8 @@ const char *const __man_macronames[MAN_MAX] = {
        "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;
@@ -428,16 +429,22 @@ man_ptext(struct man *man, int line, char *buf, int offs)
                return(man_descope(man, line, offs));
        }
 
-       /* Pump blank lines directly into the backend. */
-
        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 ( ! 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);
        }
 
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>
  *
@@ -54,6 +54,8 @@ enum  mant {
        MAN_OP,
        MAN_EX,
        MAN_EE,
+       MAN_UR,
+       MAN_UE,
        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) 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
@@ -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_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);
@@ -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_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);
 }
+
+/* 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 e9cb898..d89298e 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: man_macro.c,v 1.75 2012/11/17 00:26:33 schwarze Exp $ */
+/*     $Id: man_macro.c,v 1.78 2013/12/22 13:25:17 schwarze Exp $ */
 /*
  * 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>
  *
  * 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 +88,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 */
+       { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */
+       { blk_close, 0 }, /* UE */
 };
 
 const  struct man_macro * const man_macros = __man_macros;
@@ -284,6 +286,9 @@ blk_close(MACRO_PROT_ARGS)
        case (MAN_RE):
                ntok = MAN_RS;
                break;
+       case (MAN_UE):
+               ntok = MAN_UR;
+               break;
        default:
                abort();
                /* NOTREACHED */
@@ -293,10 +298,12 @@ blk_close(MACRO_PROT_ARGS)
                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);
+               if ( ! rew_scope(MAN_BLOCK, man, MAN_PP))
+                       return(0);
+       } else 
+               man_unscope(man, nn, MANDOCERR_MAX);
 
        return(1);
 }
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>
@@ -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_UR(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_UR(DECL_ARGS);
 
 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_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;
-               p->flags &= ~(TERMP_NOBREAK | TERMP_TWOSPACE);
+               p->trailspace = 0;
+               p->flags &= ~TERMP_NOBREAK;
                p->flags |= TERMP_NOSPACE;
        }
 
@@ -531,7 +536,7 @@ pre_HP(DECL_ARGS)
 
        if ( ! (MANT_LITERAL & mt->fl)) {
                p->flags |= TERMP_NOBREAK;
-               p->flags |= TERMP_TWOSPACE;
+               p->trailspace = 2;
        }
 
        len = mt->lmargin[mt->lmargincur];
@@ -566,7 +571,7 @@ post_HP(DECL_ARGS)
        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;
@@ -609,6 +614,7 @@ pre_IP(DECL_ARGS)
                break;
        case (MAN_HEAD):
                p->flags |= TERMP_NOBREAK;
+               p->trailspace = 1;
                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;
+               p->trailspace = 0;
                p->rmargin = p->maxrmargin;
                break;
        case (MAN_BODY):
                term_newln(p);
+               p->offset = mt->offset;
                break;
        default:
                break;
@@ -693,6 +701,7 @@ pre_TP(DECL_ARGS)
        switch (n->type) {
        case (MAN_HEAD):
                p->flags |= TERMP_NOBREAK;
+               p->trailspace = 1;
                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;
+               p->trailspace = 0;
                p->flags &= ~TERMP_NOBREAK;
-               p->flags &= ~TERMP_TWOSPACE;
                break;
        default:
                break;
@@ -762,6 +771,7 @@ post_TP(DECL_ARGS)
                break;
        case (MAN_BODY):
                term_newln(p);
+               p->offset = mt->offset;
                break;
        default:
                break;
@@ -939,6 +949,32 @@ post_RS(DECL_ARGS)
                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)
 {
@@ -1069,6 +1105,7 @@ print_man_foot(struct termp *p, const void *arg)
        /* 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;
 
@@ -1091,6 +1128,7 @@ print_man_foot(struct termp *p, const void *arg)
 
        p->flags &= ~TERMP_NOBREAK;
        p->flags |= TERMP_NOSPACE;
+       p->trailspace = 0;
        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;
+       p->trailspace = 1;
        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;
+       p->trailspace = 0;
        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) 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
@@ -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_head1(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_ur[] = { check_head1, check_part, NULL };
 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_ur }, /* UR */
+       { NULL, NULL }, /* UE */
 };
 
 
@@ -245,6 +249,17 @@ INEQ_DEFINE(1, <=, le1)
 INEQ_DEFINE(2, >=, ge2)
 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)
 {
index f6706e3..4cf093f 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>
@@ -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.
 .\"
-.Dd $Mdocdate: September 16 2013 $
+.Dd $Mdocdate: October 5 2013 $
 .Dt MANDOC 3
 .Os
 .Sh NAME
@@ -50,8 +50,8 @@
 .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 *"
index df51022..2936ef9 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.70 2013/11/10 21:34:04 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2011, 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -40,7 +40,7 @@ static        char    *time2a(time_t);
 
 
 enum mandoc_esc
-mandoc_escape(const char **end, const char **start, int *sz)
+mandoc_escape(const char const **end, const char const **start, int *sz)
 {
        const char      *local_start;
        int              local_sz;
@@ -93,8 +93,11 @@ mandoc_escape(const char **end, const char **start, int *sz)
        case ('C'):
                if ('\'' != **start)
                        return(ESCAPE_ERROR);
-               gly = ESCAPE_SPECIAL;
                *start = ++*end;
+               if ('u' == (*start)[0] && '\'' != (*start)[1])
+                       gly = ESCAPE_UNICODE;
+               else
+                       gly = ESCAPE_SPECIAL;
                term = '\'';
                break;
 
index c2406e9..5170b41 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.111 2013/10/05 20:30:05 schwarze Exp $ */
 /*
  * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012, 2013 Ingo Schwarze <schwarze@openbsd.org>
@@ -400,7 +400,8 @@ struct      man;
 __BEGIN_DECLS
 
 void            *mandoc_calloc(size_t, size_t);
-enum mandoc_esc          mandoc_escape(const char **, const char **, int *);
+enum mandoc_esc          mandoc_escape(const char const **,
+                       const char const **, int *);
 void            *mandoc_malloc(size_t);
 void            *mandoc_realloc(void *, size_t);
 char            *mandoc_strdup(const char *);
index 23ccc0a..d0a91c2 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.55 2013/12/22 13:18:27 schwarze Exp $
 .\"
 .\" 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.
 .\"
-.Dd $Mdocdate: July 13 2013 $
+.Dd $Mdocdate: November 10 2013 $
 .Dt MANDOC_CHAR 7
 .Os
 .Sh NAME
@@ -655,13 +655,18 @@ manual.
 .It \e*(Ai   Ta \*(Ai       Ta ANSI standard name
 .El
 .Sh UNICODE CHARACTERS
-The escape sequence
+The escape sequences
 .Pp
-.Dl \e[uXXXX]
+.Dl \e[uXXXX] and \eC'uXXXX'
 .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.
-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
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>
 #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 <db.h>
+#elif defined(__linux__)
+# include <endian.h>
+#elif defined(__sun)
+# include <sys/byteorder.h>
+# include <sys/stat.h>
 #else
 # include <sys/endian.h>
-# include <db.h>
 #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"
@@ -620,6 +622,8 @@ index_merge(const struct of *of, struct mparse *mp,
        uint64_t         vbuf[2];
        char             type;
 
+       static char      emptystring[] = "";
+
        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++)
-                               *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)
-                               val.data = "";
+                               val.data = emptystring;
                        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>
@@ -209,7 +209,7 @@ manpath_manconf(struct manpaths *dirs, const char *file)
                if (strncmp(MAN_CONF_KEY, p, keysz))
                        continue;
                p += keysz;
-               while (isspace(*p))
+               while (isspace((unsigned char)*p))
                        p++;
                if ('\0' == *p)
                        continue;
index c7e5866..f57506a 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mdoc.7,v 1.220 2013/08/14 15:08:31 schwarze Exp $
+.\"    $Id: mdoc.7,v 1.222 2013/11/02 20:39:49 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2010, 2011 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.
 .\"
-.Dd $Mdocdate: August 14 2013 $
+.Dd $Mdocdate: October 6 2013 $
 .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)
+.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:
@@ -1407,9 +1408,12 @@ See also
 .Sx \&Er
 and
 .Sx \&Ev
-for special-purpose constants and
+for special-purpose constants,
 .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
@@ -1570,15 +1574,32 @@ See also
 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 .
-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
-.Sx MANUAL STRUCTURE
+.Sx MANUAL STRUCTURE ,
+.Sx \&In ,
 and
-.Sx \&In .
+.Sx \&Dv .
 .Ss \&Fl
 Command-line flag or option.
 Used when listing arguments to command-line utilities.
index df68229..228728f 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.205 2013/10/21 23:47:58 schwarze Exp $ */
 /*
  * 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
@@ -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.
         */
-       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) :
@@ -584,6 +582,23 @@ mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p)
        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)
index a9503ff..83f8077 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.88 2013/12/22 14:06:36 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2012 Ingo Schwarze <schwarze@openbsd.org>
@@ -447,6 +447,7 @@ args(struct mdoc *mdoc, int line, int *pos,
                char *buf, enum argsflag fl, char **v)
 {
        char            *p, *pp;
+       int              pairs;
        enum margserr    rc;
 
        if ('\0' == buf[*pos]) {
@@ -540,6 +541,8 @@ args(struct mdoc *mdoc, int line, int *pos,
        /* 
         * Process a quoted literal.  A quote begins with a double-quote
         * and ends with a double-quote NOT preceded by a double-quote.
+        * Null-terminate the literal in place.
+        * Collapse pairs of quotes inside quoted literals.
         * 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;
 
+               pairs = 0;
                for ( ; buf[*pos]; (*pos)++) {
+                       /* Move following text left after quoted quotes. */
+                       if (pairs)
+                               buf[*pos - pairs] = buf[*pos];
                        if ('\"' != buf[*pos])
                                continue;
+                       /* Unquoted quotes end quoted args. */
                        if ('\"' != buf[*pos + 1])
                                break;
+                       /* Quoted quotes collapse. */
+                       pairs++;
                        (*pos)++;
                }
+               if (pairs)
+                       buf[*pos - pairs] = '\0';
 
                if ('\0' == buf[*pos]) {
                        if (MDOC_PPHRASE & mdoc->flags)
index 0a50486..4a018ee 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.123 2013/10/21 23:47:58 schwarze Exp $ */
 /*
  * 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
@@ -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             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 *);
@@ -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] = {
-       { 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 */
-       { 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_exp_close, MDOC_EXPLICIT }, /* Ed */
+       { blk_exp_close, MDOC_EXPLICIT | MDOC_JOIN }, /* Ed */
        { 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 }, /* 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, 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 }, /* 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, 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 */
-       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */ 
+       { in_line_argn, MDOC_CALLABLE | MDOC_PARSED }, /* St */
        { 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_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 }, /* %O */
+       { in_line_eoln, MDOC_JOIN }, /* %O */
        { 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 */
-       { 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 */
-       { 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 */
-       { 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 */
-       { 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 */
-       { 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 */
-       { 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_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, 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_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_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_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 }, /* 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 */
-       { 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 */
-       { 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;
@@ -588,13 +607,21 @@ rew_sub(enum mdoc_type t, struct mdoc *mdoc,
  * 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 (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);
 
@@ -638,7 +665,7 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf)
                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
@@ -680,6 +707,9 @@ blk_exp_close(MACRO_PROT_ARGS)
        case (MDOC_Ec):
                maxargs = 1;
                break;
+       case (MDOC_Ek):
+               if ( ! (MDOC_SYNOPSIS & mdoc->flags))
+                       mdoc->flags &= ~MDOC_KEEP;
        default:
                maxargs = 0;
                break;
@@ -782,7 +812,8 @@ blk_exp_close(MACRO_PROT_ARGS)
                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;
                }
@@ -948,7 +979,8 @@ in_line(MACRO_PROT_ARGS)
                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);
 
                /*
@@ -1067,7 +1099,10 @@ blk_full(MACRO_PROT_ARGS)
                if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
                        return(0);
                body = mdoc->last;
-       } 
+       }
+
+       if (MDOC_Bk == tok)
+               mdoc->flags |= MDOC_KEEP;
 
        ac = ARGS_ERROR;
 
@@ -1112,7 +1147,7 @@ blk_full(MACRO_PROT_ARGS)
                                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;
                }
@@ -1165,7 +1200,8 @@ blk_full(MACRO_PROT_ARGS)
                        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;
                }
@@ -1276,10 +1312,10 @@ blk_part_imp(MACRO_PROT_ARGS)
 
                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;
-               } 
+               }
 
                if (NULL == body) {
                       if ( ! mdoc_body_alloc(mdoc, line, ppos, tok))
@@ -1290,7 +1326,8 @@ blk_part_imp(MACRO_PROT_ARGS)
                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;
                }
@@ -1416,10 +1453,10 @@ blk_part_exp(MACRO_PROT_ARGS)
                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;
-               } 
+               }
 
                if (NULL == head) {
                        assert(NULL == body);
@@ -1437,7 +1474,7 @@ blk_part_exp(MACRO_PROT_ARGS)
                        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))
@@ -1455,7 +1492,8 @@ blk_part_exp(MACRO_PROT_ARGS)
                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;
                }
@@ -1559,7 +1597,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 ( ! dword(mdoc, line, la, p, DELIM_OPEN))
+                       if ( ! dword(mdoc, line, la, p, DELIM_OPEN, 0))
                                return(0);
                        continue;
                } else if (0 == j)
@@ -1593,7 +1631,8 @@ in_line_argn(MACRO_PROT_ARGS)
                        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++;
        }
@@ -1664,7 +1703,8 @@ in_line_eoln(MACRO_PROT_ARGS)
                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;
                }
@@ -1744,7 +1784,7 @@ phrase(struct mdoc *mdoc, int line, int ppos, char *buf)
                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;
                }
@@ -1795,7 +1835,8 @@ phrase_ta(MACRO_PROT_ARGS)
                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;
                }
index 99c5953..7207df3 100644 (file)
@@ -1,7 +1,7 @@
-/*     $Id: mdoc_term.c,v 1.249 2013/06/02 18:16:57 schwarze Exp $ */
+/*     $Id: mdoc_term.c,v 1.251 2013/12/23 02:20:09 schwarze Exp $ */
 /*
  * 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
@@ -424,6 +424,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->trailspace = 1;
        p->flags |= TERMP_NOSPACE | TERMP_NOBREAK;
 
        term_word(p, meta->os);
@@ -438,6 +439,7 @@ print_mdoc_foot(struct termp *p, const void *arg)
 
        p->offset = p->rmargin;
        p->rmargin = p->maxrmargin;
+       p->trailspace = 0;
        p->flags &= ~TERMP_NOBREAK;
        p->flags |= TERMP_NOSPACE;
 
@@ -489,6 +491,7 @@ print_mdoc_head(struct termp *p, const void *arg)
        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 -
@@ -507,6 +510,7 @@ print_mdoc_head(struct termp *p, const void *arg)
        term_flushln(p);
 
        p->flags &= ~TERMP_NOBREAK;
+       p->trailspace = 0;
        if (p->rmargin + titlen <= p->maxrmargin) {
                p->flags |= TERMP_NOSPACE;
                p->offset = p->rmargin;
@@ -794,13 +798,13 @@ termp_it_pre(DECL_ARGS)
        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):
-               if (MDOC_HEAD == n->type)
-                       p->flags |= TERMP_NOBREAK;
-               else
+               if (MDOC_HEAD != n->type)
                        break;
 
                /*
@@ -812,16 +816,18 @@ termp_it_pre(DECL_ARGS)
                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):
-               if (MDOC_HEAD == n->type)
-                       p->flags |= TERMP_NOBREAK | TERMP_TWOSPACE;
-
                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;
@@ -829,15 +835,20 @@ termp_it_pre(DECL_ARGS)
                if (MDOC_HEAD == n->type)
                        break;
 
-               if (NULL == n->next)
+               if (NULL == n->next) {
                        p->flags &= ~TERMP_NOBREAK;
-               else
+                       p->trailspace = 0;
+               } else {
                        p->flags |= TERMP_NOBREAK;
+                       p->trailspace = 1;
+               }
 
                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;
@@ -989,8 +1000,8 @@ termp_it_post(DECL_ARGS)
 
        p->flags &= ~TERMP_DANGLE;
        p->flags &= ~TERMP_NOBREAK;
-       p->flags &= ~TERMP_TWOSPACE;
        p->flags &= ~TERMP_HANG;
+       p->trailspace = 0;
 }
 
 
@@ -1023,6 +1034,7 @@ termp_nm_pre(DECL_ARGS)
 
        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);
@@ -1051,6 +1063,7 @@ termp_nm_post(DECL_ARGS)
        if (MDOC_HEAD == n->type && n->next->child) {
                term_flushln(p);
                p->flags &= ~(TERMP_NOBREAK | TERMP_HANG);
+               p->trailspace = 0;
        } else if (MDOC_BODY == n->type && n->child)
                term_flushln(p);
 }
@@ -1525,6 +1538,7 @@ termp_ft_pre(DECL_ARGS)
 static int
 termp_fn_pre(DECL_ARGS)
 {
+       size_t           width, rmargin = 0;
        int              pretty;
 
        pretty = MDOC_SYNPRETTY & n->flags;
@@ -1534,11 +1548,25 @@ termp_fn_pre(DECL_ARGS)
        if (NULL == (n = n->child))
                return(0);
 
+       if (pretty) {
+               width = term_len(p, 4);
+               rmargin = p->rmargin;
+               p->rmargin = p->offset + width;
+               p->flags |= TERMP_NOBREAK | TERMP_HANG;
+       }
+
        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;
@@ -1561,6 +1589,7 @@ termp_fn_pre(DECL_ARGS)
        if (pretty) {
                p->flags |= TERMP_NOSPACE;
                term_word(p, ";");
+               term_flushln(p);
        }
 
        return(0);
index 1655692..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) 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
@@ -889,8 +889,6 @@ pre_sh(PRE_ARGS)
 
        if (MDOC_BLOCK != n->type)
                return(1);
-
-       roff_regunset(mdoc->roff, REG_nS);
        return(check_parent(mdoc, n, MDOC_MAX, MDOC_ROOT));
 }
 
@@ -1676,10 +1674,16 @@ ebool(struct mdoc *mdoc)
 
        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);
-       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);
+       }
 
        mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_BADBOOL);
        return(1);
@@ -1986,10 +1990,13 @@ post_sh_head(POST_ARGS)
 
        /* 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;
-       else
+       } else {
+               roff_setreg(mdoc->roff, "nS", 0, '=');
                mdoc->flags &= ~MDOC_SYNOPSIS;
+       }
 
        /* 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>
@@ -142,7 +142,6 @@ void
 tblcalc(struct rofftbl *tbl, const struct tbl_span *sp)
 {
        const struct tbl_dat    *dp;
-       const struct tbl_head   *hp;
        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));
 
-       hp = sp->head;
-
        for ( ; sp; sp = sp->next) {
                if (TBL_SPAN_DATA != sp->pos)
                        continue;
index 7c26086..bc55074 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: roff.7,v 1.42 2013/08/08 20:07:47 schwarze Exp $
+.\"    $Id: roff.7,v 1.45 2013/12/15 21:23:52 schwarze Exp $
 .\"
 .\" Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2010, 2011 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.
 .\"
-.Dd $Mdocdate: August 8 2013 $
+.Dd $Mdocdate: October 22 2013 $
 .Dt ROFF 7
 .Os
 .Sh NAME
@@ -638,6 +638,15 @@ Begin an equation block.
 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.
@@ -805,19 +814,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
-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
-.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.
-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
-is recognised:
+is handled specially:
 .Bl -tag -width Ds
 .It Cm nS
 If set to a positive integer value, certain
index 3ee8adf..e4c43c1 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.187 2013/12/15 21:23:52 schwarze Exp $ */
 /*
  * 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_fam,
+       ROFF_hw,
        ROFF_hy,
        ROFF_ie,
        ROFF_if,
@@ -74,18 +76,8 @@ enum rofft {
 };
 
 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 */
 };
 
+/*
+ * 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 */
@@ -112,7 +113,7 @@ struct      roff {
        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') */
@@ -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 void             roff_freereg(struct roffreg *);
 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);
@@ -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 },
+       { "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 },
@@ -424,6 +432,10 @@ roff_free1(struct roff *r)
 
        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);
@@ -440,7 +452,6 @@ roff_reset(struct roff *r)
        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);
@@ -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)
 {
-       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 */
-       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;
 
@@ -501,7 +513,7 @@ again:
                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.
                 */
@@ -509,12 +521,16 @@ again:
                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;
-                       cp = res;
                        mandoc_msg
                                (MANDOCERR_BADESCAPE, r->parse, 
                                 ln, (int)(stesc - *bufp), NULL);
@@ -525,7 +541,7 @@ again:
 
                /*
                 * 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.
                 */
 
@@ -548,7 +564,7 @@ again:
 
                /* 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, 
@@ -565,7 +581,11 @@ again:
                 * 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
@@ -579,15 +599,15 @@ again:
                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);
 
-               *bufp = n;
+               *bufp = nbuf;
                *szp = nsz;
 
                if (EXPAND_LIMIT >= ++expand_count)
@@ -627,7 +647,7 @@ roff_parsetext(char **bufp, size_t *szp, int pos, int *offs)
                        /* Skip over escapes. */
                        p++;
                        esc = mandoc_escape
-                               ((const char **)&p, NULL, NULL);
+                               ((const char const **)&p, NULL, NULL);
                        if (ESCAPE_ERROR == esc)
                                break;
                        continue;
@@ -698,19 +718,14 @@ roff_parseln(struct roff *r, int ln, char **bufp,
                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));
-       } 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,
@@ -1116,9 +1131,61 @@ roff_cond_text(ROFF_ARGS)
        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)
 {
+       int      not, lh, rh;
+       char     op;
 
        switch (v[*pos]) {
        case ('n'):
@@ -1131,13 +1198,47 @@ roff_evalcond(const char *v, int *pos)
        case ('t'):
                (*pos)++;
                return(ROFFRULE_DENY);
+       case ('!'):
+               (*pos)++;
+               not = 1;
+               break;
        default:
+               not = 0;
                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 */
@@ -1258,25 +1359,71 @@ roff_ds(ROFF_ARGS)
        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
-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 */
@@ -1285,18 +1432,21 @@ roff_nr(ROFF_ARGS)
 {
        const char      *key;
        char            *val;
+       size_t           sz;
        int              iv;
+       char             sign;
 
        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);
 }
index 16def78..3420c70 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.212 2013/12/23 02:20:09 schwarze Exp $ */
 /*
  * 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_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.
@@ -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
-        * 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;
@@ -200,7 +204,11 @@ term_flushln(struct termp *p)
                        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;
@@ -269,15 +277,17 @@ term_flushln(struct termp *p)
        }
 
        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 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;
 
@@ -285,8 +295,7 @@ term_flushln(struct termp *p)
                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;
        }
index 6aa9934..f49e86f 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.95 2013/12/22 23:34:13 schwarze Exp $ */
 /*
  * 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
@@ -63,6 +64,7 @@ struct        termp {
        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;
@@ -73,7 +75,6 @@ struct        termp {
 #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_NOSPLIT    (1 << 11)      /* See termp_an_pre/post(). */
 #define        TERMP_SPLIT      (1 << 12)      /* See termp_an_pre/post(). */
 #define        TERMP_ANPREC     (1 << 13)      /* See termp_an_pre(). */