Merge release 1.10.4 (all code by kristaps@), providing four new features:
authorschwarze <schwarze@openbsd.org>
Tue, 13 Jul 2010 01:09:12 +0000 (01:09 +0000)
committerschwarze <schwarze@openbsd.org>
Tue, 13 Jul 2010 01:09:12 +0000 (01:09 +0000)
1) Proper .Bk support: allow output line breaks at input line breaks,
but keep input lines together in the output, finally fixing
synopses like aucat(1), mail(1) and tmux(1).
2) Mostly finished -Tps (PostScript) output.
3) Implement -Thtml output for .Nm blocks and .Bk -words.
4) Allow iterative interpolation of user-defined roff(7) strings.
Also contains some minor bugfixes and some performance improvements.

31 files changed:
usr.bin/mandoc/Makefile
usr.bin/mandoc/html.c
usr.bin/mandoc/html.h
usr.bin/mandoc/libman.h
usr.bin/mandoc/libmdoc.h
usr.bin/mandoc/main.c
usr.bin/mandoc/man.3
usr.bin/mandoc/man.c
usr.bin/mandoc/man_html.c
usr.bin/mandoc/man_term.c
usr.bin/mandoc/mandoc.1
usr.bin/mandoc/mandoc.h
usr.bin/mandoc/mdoc.3
usr.bin/mandoc/mdoc.7
usr.bin/mandoc/mdoc.c
usr.bin/mandoc/mdoc.h
usr.bin/mandoc/mdoc_action.c
usr.bin/mandoc/mdoc_argv.c
usr.bin/mandoc/mdoc_html.c
usr.bin/mandoc/mdoc_macro.c
usr.bin/mandoc/mdoc_term.c
usr.bin/mandoc/mdoc_validate.c
usr.bin/mandoc/regs.h [deleted file]
usr.bin/mandoc/roff.3
usr.bin/mandoc/roff.7
usr.bin/mandoc/roff.c
usr.bin/mandoc/term.c
usr.bin/mandoc/term.h
usr.bin/mandoc/term_ascii.c
usr.bin/mandoc/term_ps.c
usr.bin/mandoc/tree.c

index 0ef7c42..45cb799 100644 (file)
@@ -1,8 +1,8 @@
-#      $OpenBSD: Makefile,v 1.42 2010/06/29 15:49:52 schwarze Exp $
+#      $OpenBSD: Makefile,v 1.43 2010/07/13 01:09:12 schwarze Exp $
 
 .include <bsd.own.mk>
 
-VERSION=1.10.3
+VERSION=1.10.4
 CFLAGS+=-DVERSION=\"${VERSION}\"
 CFLAGS+=-W -Wall -Wstrict-prototypes
 
index b348afc..16cdb29 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: html.c,v 1.11 2010/06/27 20:28:56 schwarze Exp $ */
+/*     $Id: html.c,v 1.12 2010/07/13 01:09:12 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -389,8 +389,15 @@ print_otag(struct html *h, enum htmltag tag,
                t = NULL;
 
        if ( ! (HTML_NOSPACE & h->flags))
-               if ( ! (HTML_CLRLINE & htmltags[tag].flags))
-                       putchar(' ');
+               if ( ! (HTML_CLRLINE & htmltags[tag].flags)) {
+                       /* Manage keeps! */
+                       if ( ! (HTML_KEEP & h->flags)) {
+                               if (HTML_PREKEEP & h->flags)
+                                       h->flags |= HTML_KEEP;
+                               putchar(' ');
+                       } else
+                               printf("&#160;");
+               }
 
        /* Print out the tag name and attributes. */
 
@@ -480,11 +487,11 @@ print_doctype(struct html *h)
 
 
 void
-print_text(struct html *h, const char *p)
+print_text(struct html *h, const char *word)
 {
 
-       if (*p && 0 == *(p + 1))
-               switch (*p) {
+       if (word[0] && '\0' == word[1])
+               switch (word[0]) {
                case('.'):
                        /* FALLTHROUGH */
                case(','):
@@ -507,19 +514,26 @@ print_text(struct html *h, const char *p)
                        break;
                }
 
-       if ( ! (h->flags & HTML_NOSPACE))
-               putchar(' ');
+       if ( ! (HTML_NOSPACE & h->flags)) {
+               /* Manage keeps! */
+               if ( ! (HTML_KEEP & h->flags)) {
+                       if (HTML_PREKEEP & h->flags)
+                               h->flags |= HTML_KEEP;
+                       putchar(' ');
+               } else
+                       printf("&#160;");
+       }
 
-       assert(p);
-       if ( ! print_encode(h, p, 0))
+       assert(word);
+       if ( ! print_encode(h, word, 0))
                h->flags &= ~HTML_NOSPACE;
 
        /* 
         * Note that we don't process the pipe: the parser sees it as
         * punctuation, but we don't in terms of typography.
         */
-       if (*p && 0 == *(p + 1))
-               switch (*p) {
+       if (word[0] && '\0' == word[1])
+               switch (word[0]) {
                case('('):
                        /* FALLTHROUGH */
                case('['):
index 7bb789c..bd97349 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: html.h,v 1.6 2010/04/07 23:15:05 schwarze Exp $ */
+/*     $Id: html.h,v 1.7 2010/07/13 01:09:12 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -110,7 +110,9 @@ enum        htmltype {
 struct html {
        int               flags;
 #define        HTML_NOSPACE     (1 << 0)
-#define        HTML_IGNDELIM    (1 << 2)
+#define        HTML_IGNDELIM    (1 << 1)
+#define        HTML_KEEP        (1 << 2)
+#define        HTML_PREKEEP     (1 << 3)
        struct tagq       tags;
        struct ordq       ords;
        void             *symtab;
index e26ab2a..0ef8b21 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: libman.h,v 1.23 2010/06/27 21:54:41 schwarze Exp $ */
+/*     $Id: libman.h,v 1.24 2010/07/13 01:09:12 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,7 +17,6 @@
 #ifndef LIBMAN_H
 #define LIBMAN_H
 
-#include "regs.h"
 #include "man.h"
 
 enum   man_next {
index c4e0f7b..53ba8ba 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: libmdoc.h,v 1.40 2010/07/01 22:31:52 schwarze Exp $ */
+/*     $Id: libmdoc.h,v 1.41 2010/07/13 01:09:12 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -17,7 +17,6 @@
 #ifndef LIBMDOC_H
 #define LIBMDOC_H
 
-#include "regs.h"
 #include "mdoc.h"
 
 enum   mdoc_next {
index d676aa4..53b4e7b 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: main.c,v 1.41 2010/07/01 15:36:59 schwarze Exp $ */
+/*     $Id: main.c,v 1.42 2010/07/13 01:09:12 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 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
@@ -27,7 +28,6 @@
 #include <unistd.h>
 
 #include "mandoc.h"
-#include "regs.h"
 #include "main.h"
 #include "mdoc.h"
 #include "man.h"
@@ -142,13 +142,13 @@ static    const char * const      mandocerrs[MANDOCERR_MAX] = {
        "no title in document",
        "missing list type",
        "missing display type",
+       "missing font type",
        "line argument(s) will be lost",
        "body argument(s) will be lost",
 
        "generic fatal error",
 
        "column syntax is inconsistent",
-       "missing font type",
        "displays may not be nested",
        "unsupported display type",
        "blocks badly nested",
index 2edd6a0..8f42388 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: man.3,v 1.12 2010/06/27 21:54:42 schwarze Exp $
+.\"    $Id: man.3,v 1.13 2010/07/13 01:09:12 schwarze Exp $
 .\"
 .\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
@@ -14,7 +14,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: June 27 2010 $
+.Dd $Mdocdate: July 13 2010 $
 .Dt MAN 3
 .Os
 .Sh NAME
@@ -29,7 +29,6 @@
 .Nd man macro compiler library
 .Sh SYNOPSIS
 .In mandoc.h
-.In regs.h
 .In man.h
 .Vt extern const char * const * man_macronames;
 .Ft "struct man *"
index 71acf9f..9ac7f5f 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man.c,v 1.35 2010/06/27 21:54:42 schwarze Exp $ */
+/*     $Id: man.c,v 1.36 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -24,7 +24,6 @@
 #include <string.h>
 
 #include "mandoc.h"
-#include "regs.h"
 #include "libman.h"
 #include "libmandoc.h"
 
index bbe7a7a..8b77f12 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_html.c,v 1.16 2010/06/27 21:54:42 schwarze Exp $ */
+/*     $Id: man_html.c,v 1.17 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -25,7 +25,6 @@
 #include "mandoc.h"
 #include "out.h"
 #include "html.h"
-#include "regs.h"
 #include "man.h"
 #include "main.h"
 
index 868f93a..dfb4463 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_term.c,v 1.43 2010/06/27 21:54:42 schwarze Exp $ */
+/*     $Id: man_term.c,v 1.44 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -24,7 +24,6 @@
 
 #include "mandoc.h"
 #include "out.h"
-#include "regs.h"
 #include "man.h"
 #include "term.h"
 #include "chars.h"
index 7fa4db7..e0fa0b1 100644 (file)
@@ -1,6 +1,6 @@
-.\"    $OpenBSD: mandoc.1,v 1.34 2010/06/29 15:49:52 schwarze Exp $
+.\"    $OpenBSD: mandoc.1,v 1.35 2010/07/13 01:09:13 schwarze Exp $
 .\"
-.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
 .\" Permission to use, copy, modify, and distribute this software for any
 .\" purpose with or without fee is hereby granted, provided that the above
@@ -14,7 +14,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: June 29 2010 $
+.Dd $Mdocdate: July 13 2010 $
 .Dt MANDOC 1
 .Os
 .Sh NAME
@@ -302,8 +302,10 @@ PostScript
 .Qq Adobe-3.0
 Level-2 pages may be generated by
 .Fl T Ns Cm ps .
-Output pages are US-letter sized and rendered in fixed, 10-point Courier
-font.
+Output pages default to letter sized and are rendered in the Times font
+family, 11-point.
+Margins are calculated as 1/9 the page length and width.
+Line-height is 1.4m.
 .Pp
 Special characters are rendered as in
 .Sx ASCII Output .
@@ -316,9 +318,18 @@ arguments are accepted:
 The paper size
 .Ar name
 may be one of
-.Ar a4
+.Ar a3 ,
+.Ar a4 ,
+.Ar a5 ,
+.Ar legal ,
 or
 .Ar letter .
+You may also manually specify dimensions as
+.Ar NNxNN ,
+width by height in millimetres.
+If an unknown value is encountered,
+.Ar letter
+is used.
 .El
 .Ss XHTML Output
 Output produced by
index 6abf61d..53b239b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.h,v 1.9 2010/07/01 15:36:59 schwarze Exp $ */
+/*     $Id: mandoc.h,v 1.10 2010/07/13 01:09:13 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 #ifndef MANDOC_H
 #define MANDOC_H
 
+/*
+ * This contains declarations that are available system-wide.
+ */
+
 #define ASCII_NBRSP     31  /* non-breaking space */
 #define        ASCII_HYPH       30  /* breakable hyphen */
 
-
 __BEGIN_DECLS
 
 enum   mandocerr {
@@ -81,6 +84,7 @@ enum  mandocerr {
        MANDOCERR_NOTITLE, /* no title in document */
        MANDOCERR_LISTTYPE, /* missing list type */
        MANDOCERR_DISPTYPE, /* missing display type */
+       MANDOCERR_FONTTYPE, /* missing font type */
        MANDOCERR_ARGSLOST, /* line argument(s) will be lost */
        MANDOCERR_BODYLOST, /* body argument(s) will be lost */
 
@@ -88,8 +92,6 @@ enum  mandocerr {
 
        MANDOCERR_COLUMNS, /* column syntax is inconsistent */
        /* FIXME: this should be a MANDOCERR_ERROR */
-       MANDOCERR_FONTTYPE, /* missing font type */
-       /* FIXME: this should be a MANDOCERR_ERROR */
        MANDOCERR_NESTEDDISP, /* displays may not be nested */
        MANDOCERR_BADDISP, /* unsupported display type */
        MANDOCERR_SCOPEFATAL, /* blocks badly nested */
@@ -107,8 +109,39 @@ enum       mandocerr {
        MANDOCERR_MAX
 };
 
-typedef        int     (*mandocmsg)(enum mandocerr, 
-                       void *, int, int, const char *);
+enum   regs {
+       REG_nS = 0,     /* register: nS */
+       REG__MAX
+};
+
+/*
+ * A single register entity.  If "set" is zero, the value of the
+ * register should be the default one, which is per-register.  It's
+ * assumed that callers know which type in "v" corresponds to which
+ * register value.
+ */
+struct reg {
+       int               set; /* whether set or not */
+       union {
+               unsigned  u; /* unsigned integer */
+       } v;
+};
+
+/*
+ * The primary interface to setting register values is in libroff,
+ * although libmdoc and libman from time to time will manipulate
+ * registers (such as `.Sh SYNOPSIS' enabling REG_nS).
+ */
+struct regset {
+       struct reg        regs[REG__MAX];
+};
+
+/*
+ * Callback function for warnings, errors, and fatal errors as they
+ * occur in the compilers libroff, libmdoc, and libman.
+ */
+typedef        int             (*mandocmsg)(enum mandocerr, void *,
+                               int, int, const char *);
 
 __END_DECLS
 
index 70efdb6..f498c8c 100644 (file)
@@ -1,6 +1,7 @@
-.\"    $Id: mdoc.3,v 1.10 2010/06/29 17:10:29 schwarze Exp $
+.\"    $Id: mdoc.3,v 1.11 2010/07/13 01:09:13 schwarze Exp $
 .\"
-.\" Copyright (c) 2009-2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010 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
@@ -14,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: June 29 2010 $
+.Dd $Mdocdate: July 13 2010 $
 .Dt MDOC 3
 .Os
 .Sh NAME
@@ -29,7 +30,6 @@
 .Nd mdoc macro compiler library
 .Sh SYNOPSIS
 .In mandoc.h
-.In regs.h
 .In mdoc.h
 .Vt extern const char * const * mdoc_macronames;
 .Vt extern const char * const * mdoc_argnames;
@@ -257,10 +257,10 @@ an empty line will produce a zero-length string.
 Multiple body parts are only found in invocations of
 .Sq \&Bl \-column ,
 where a new body introduces a new phrase.
-.Ss Badly nested blocks
-A special kind of node is available to end the formatting
-associated with a given block before the physical end of that block.
-Such an ENDBODY node has a non-null
+.Ss Badly-nested Blocks
+The ENDBODY node is available to end the formatting associated
+with a given block before the physical end of that block.
+It has a non-null
 .Va end
 field, is of the BODY
 .Va type ,
@@ -297,25 +297,32 @@ BLOCK Ao
 TEXT end
 .Ed
 .Pp
-Here, the formatting of the Ao block extends from TEXT ao to TEXT ac,
-while the formatting of the Bo block extends from TEXT bo to TEXT bc,
-rendering like this in
+Here, the formatting of the
+.Sq \&Ao
+block extends from TEXT ao to TEXT ac,
+while the formatting of the
+.Sq \&Bo
+block extends from TEXT bo to TEXT bc.
+It renders as follows in
 .Fl T Ns Cm ascii
 mode:
+.Pp
 .Dl <ao [bo ac> bc] end
-Support for badly nested blocks is only provided for backward
+.Pp
+Support for badly-nested blocks is only provided for backward
 compatibility with some older
 .Xr mdoc 7
 implementations.
-Using them in new code is stronly discouraged:
-Some frontends, in particular
-.Fl T Ns Cm html ,
-are unable to render them in any meaningful way,
-many other
-.Xr mdoc 7
-implementations do not support them, and even for those that do,
-the behaviour is not well-defined, in particular when using multiple
-levels of badly nested blocks.
+Using badly-nested blocks is
+.Em strongly discouraged :
+the
+.Fl T Ns Cm html
+and
+.Fl T Ns Cm xhtml
+front-ends are unable to render them in any meaningful way.
+Furthermore, behaviour when encountering badly-nested blocks is not
+consistent across troff implementations, especially when using  multiple
+levels of badly-nested blocks.
 .Sh EXAMPLES
 The following example reads lines from stdin and parses them, operating
 on the finished parse tree with
index 2f1d065..3cc5c85 100644 (file)
@@ -1,6 +1,7 @@
-.\"    $Id: mdoc.7,v 1.38 2010/07/01 15:36:59 schwarze Exp $
+.\"    $Id: mdoc.7,v 1.39 2010/07/13 01:09:13 schwarze Exp $
 .\"
-.\" Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010 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
@@ -14,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: July 1 2010 $
+.Dd $Mdocdate: July 13 2010 $
 .Dt MDOC 7
 .Os
 .Sh NAME
@@ -1063,6 +1064,14 @@ Closes a
 block.  Does not have any tail arguments.
 .Ss \&Bd
 Begins a display block.
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Bd
+.Fl type
+.Op Fl offset Ar width
+.Op Fl compact
+.Ed
+.Pp
 A display is collection of macros or text which may be collectively
 offset or justified in a manner different from that
 of the enclosing context.
@@ -1087,9 +1096,9 @@ Centre-justify each line.
 The type must be provided first.
 Secondary arguments are as follows:
 .Bl -tag -width 12n -offset indent
-.It Fl offset Ar width
+.It Fl offset Ar val
 Offset by the value of
-.Ar width ,
+.Ar val ,
 which is interpreted as one of the following, specified in order:
 .Bl -item
 .It
@@ -1100,7 +1109,7 @@ the width of standard indentation;
 twice
 .Ar indent ;
 .Ar left ,
-which has no effect ;
+which has no effect;
 .Ar right ,
 which justifies to the right margin; and
 .Ar center ,
@@ -1121,10 +1130,6 @@ As the calculated string length of the opaque string.
 If not provided an argument, it will be ignored.
 .It Fl compact
 Do not assert a vertical space before the block.
-.It Fl file Ar file
-Prepend the file
-.Ar file
-before any text or macros within the block.
 .El
 .Pp
 Examples:
@@ -1139,28 +1144,75 @@ See also
 and
 .Sx \&Dl .
 .Ss \&Bf
+Change the font mode for a scoped block of text.
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Bf
+.Oo
+.Fl emphasis | literal | symbolic |
+.Cm \&Em | \&Li | \&Sy
+.Oc
+.Ed
+.Pp
+The
+.Fl emphasis
+and
+.Cm \&Em
+argument are equivalent, as are
+.Fl symbolic
+and
+.Cm \&Sy,
+and
+.Fl literal
+and
+.Cm \&Li .
+Without an argument, this macro does nothing.
+The font mode continues until broken by a new font mode in a nested
+scope or
+.Sx \&Ef
+is encountered.
+.Pp
+See also
+.Sx \&Li ,
+.Sx \&Ef ,
+and
+.Sx \&Sy .
 .Ss \&Bk
-Begins a keep block, containing a collection of macros or text
-to be kept together in the output.
-One argument is required; additional arguments are ignored.
-Currently, the only argument implemented is
-.Fl words ,
-requesting to keep together all words of the contained text
-on the same output line.
-A
-.Fl lines
-argument to keep together all lines of the contained text
-on the same page has been desired for a long time,
-but has never been implemented.
+Begins a collection of macros or text not breaking the line.
+Its syntax is as follows:
 .Pp
-Examples:
+.D1 Pf \. Sx \&Bk Fl words
+.Pp
+Subsequent arguments are ignored.
+The
+.Fl words
+argument is required.
+.Pp
+Each line within a keep block is kept intact, so the following example
+will not break within each
+.Sx \&Op
+macro line:
 .Bd -literal -offset indent
 \&.Bk \-words
-\&.Op o Ar output_file
+\&.Op Fl f Ar flags
+\&.Op Fl o Ar output
 \&.Ek
 .Ed
+.Pp
+Be careful in using over-long lines within a keep block!
+Doing so will clobber the right margin.
 .Ss \&Bl
 Begins a list composed of one or more list entries.
+Its syntax is as follows:
+.Bd -ragged -offset indent
+.Pf \. Sx \&Bl
+.Fl type
+.Op Fl width Ar val
+.Op Fl offset Ar val
+.Op Fl compact
+.Op HEAD ...
+.Ed
+.Pp
 A list is associated with a type, which is a required argument.
 Other arguments are
 .Fl width ,
@@ -1629,8 +1681,23 @@ See also
 and
 .Sx \&Ux .
 .Ss \&Ec
+Close a scope started by
+.Sx \&Eo .
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Ec Op Cm TERM
+.Pp
+The
+.Cm TERM
+argument is used as the enclosure tail, for example, specifying \e(rq
+will emulate
+.Sx \&Dc .
 .Ss \&Ed
+End a display context started by
+.Sx \&Bd .
 .Ss \&Ef
+Ends a font mode context started by
+.Sx \&Bf .
 .Ss \&Ek
 Ends a keep context started by
 .Sx \&Bk .
@@ -1651,7 +1718,18 @@ Examples:
 .D1 \&.Em Warnings!
 .D1 \&.Em Remarks :
 .Ss \&En
+This macro is obsolete and not implemented.
 .Ss \&Eo
+An arbitrary enclosure.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Eo Op Cm TERM
+.Pp
+The
+.Cm TERM
+argument is used as the enclosure head, for example, specifying \e(lq
+will emulate
+.Sx \&Do .
 .Ss \&Er
 Display error constants.
 .Pp
@@ -1662,6 +1740,7 @@ Examples:
 See also
 .Sx \&Dv .
 .Ss \&Es
+This macro is obsolete and not implemented.
 .Ss \&Ev
 Environmental variables such as those specified in
 .Xr environ 7 .
@@ -1712,6 +1791,8 @@ Examples:
 See also
 .Sx \&Fo .
 .Ss \&Fc
+Ends a function context started by
+.Sx \&Fo .
 .Ss \&Fd
 Historically used to document include files.
 This usage has been deprecated in favour of
@@ -1833,7 +1914,24 @@ See also
 and
 .Sx \&Ux .
 .Ss \&Hf
+This macro is obsolete and not implemented.
 .Ss \&Ic
+Designate an internal or interactive command.
+This is similar to
+.Sx \&Cm
+but used for instructions rather than values.
+.Pp
+Examples:
+.D1 \&.Ic hash
+.D1 \&.Ic alias
+.Pp
+Note that using
+.Sx \&Bd No Fl literal
+or
+.Sx \&D1
+is preferred for displaying code; the
+.Sx \&Ic
+macro is used when referring to specific instructions.
 .Ss \&In
 An
 .Qq include
@@ -1956,6 +2054,9 @@ Examples:
 .D1 \&.Lb libz
 .D1 \&.Lb mdoc
 .Ss \&Li
+Denotes text that should be in a literal font mode.
+Note that this is a presentation term and should not be used for
+stylistically decorating technical terms.
 .Ss \&Lk
 Format a hyperlink.
 Its syntax is as follows:
@@ -1969,6 +2070,8 @@ Examples:
 See also
 .Sx \&Mt .
 .Ss \&Lp
+Synonym for
+.Sx \&Pp .
 .Ss \&Ms
 .Ss \&Mt
 Format a
@@ -1981,6 +2084,29 @@ Its syntax is as follows:
 Examples:
 .D1 \&.Mt discuss@manpages.bsd.lv
 .Ss \&Nd
+A one-line description of the manual's content.
+This may only be invoked in the
+.Em SYNOPSIS
+section subsequent the
+.Sx \&Nm
+macro.
+.Pp
+Examples:
+.D1 \&.Sx \&Nd mdoc language reference
+.D1 \&.Sx \&Nd format and display UNIX manuals
+.Pp
+The
+.Sx \&Nd
+macro technically accepts child macros and terminates with a subsequent
+.Sx \&Sh
+invocation.
+Do not assume this behaviour: some
+.Xr whatis 1
+database generators are not smart enough to parse more than the line
+arguments and will display macros verbatim.
+.Pp
+See also
+.Sx \&Nm .
 .Ss \&Nm
 The name of the manual page, or \(em in particular in section 1, 6,
 and 8 pages \(em of an additional command or feature documented in
@@ -2019,6 +2145,12 @@ macro rather than
 .Sx \&Nm
 to mark up the name of the manual page.
 .Ss \&No
+A
+.Qq noop
+macro used to terminate prior macro contexts.
+.Pp
+Examples:
+.D1 \&.Sx \&Fl ab \&No cd \&Fl ef
 .Ss \&Ns
 .Ss \&Nx
 Format the NetBSD version provided as an argument, or a default value if
@@ -2038,8 +2170,30 @@ See also
 and
 .Sx \&Ux .
 .Ss \&Oc
+Closes multi-line
+.Sx \&Oo
+context.
 .Ss \&Oo
+Multi-line version of
+.Sx \&Op .
+.Pp
+Examples:
+.Bd -literal -offset indent
+\&.Oo
+\&.Op Fl flag Ns Ar value
+\&.Oc
+.Ed
 .Ss \&Op
+Command-line option.
+Used when listing options to command-line utilities.
+Prints the argument(s) in brackets.
+.Pp
+Examples:
+.D1 \&.Op \&Fl a \&Ar b
+.D1 \&.Op \&Ar a | b
+.Pp
+See also
+.Sx \&Oo .
 .Ss \&Os
 Document operating system version.
 This is the mandatory third macro of
@@ -2088,11 +2242,43 @@ See also
 and
 .Sx \&Ux .
 .Ss \&Pa
+A file-system path.
+.Pp
+Examples:
+.D1 \&.Pa /usr/bin/mandoc
+.D1 \&.Pa /usr/share/man/man7/mdoc.7
+.Pp
+See also
+.Sx \&Lk .
 .Ss \&Pc
+Close parenthesised context opened by
+.Sx \&Po .
 .Ss \&Pf
+Removes the space
+.Pq Qq prefix
+between its arguments.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. \&Pf Cm prefix suffix
+.Pp
+The
+.Cm suffix
+argument may be a macro.
+.Pp
+Examples:
+.D1 \&.Pf \e. \&Sx \&Pf \&Cm prefix suffix
 .Ss \&Po
+Multi-line version of
+.Sx \&Pq .
 .Ss \&Pp
+Break a paragraph.
+This will assert vertical space between prior and subsequent macros
+and/or text.
 .Ss \&Pq
+Parenthesised enclosure.
+.Pp
+See also
+.Sx \&Po .
 .Ss \&Qc
 .Ss \&Ql
 .Ss \&Qo
@@ -2173,6 +2359,11 @@ See also
 and
 .Sx \&Ox .
 .Ss \&Va
+A variable name.
+.Pp
+Examples:
+.D1 \&.Va foo
+.D1 \&.Va const char *bar ;
 .Ss \&Vt
 A variable type.
 This is also used for indicating global variables in the
@@ -2330,9 +2521,9 @@ Display offsets
 and
 .Fl offset Ar right
 are disregarded in mandoc.
-Furthermore, the
+Furthermore, troff specifies a
 .Fl file Ar file
-argument is not supported in mandoc.
+argument that is not supported in mandoc.
 Lastly, since text is not right-justified in mandoc (or even groff),
 .Fl ragged
 and
index f32708f..1debb67 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: mdoc.c,v 1.60 2010/07/01 22:31:52 schwarze Exp $ */
+/*     $Id: mdoc.c,v 1.61 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 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
@@ -25,7 +26,6 @@
 #include <time.h>
 
 #include "mandoc.h"
-#include "regs.h"
 #include "libmdoc.h"
 #include "libmandoc.h"
 
@@ -510,10 +510,26 @@ mdoc_word_alloc(struct mdoc *m, int line, int pos, const char *p)
 }
 
 
-void
+static void
 mdoc_node_free(struct mdoc_node *p)
 {
 
+       /*
+        * XXX: if these end up being problematic in terms of memory
+        * management and dereferencing freed blocks, then make them
+        * into reference-counted double-pointers.
+        */
+
+       if (MDOC_Bd == p->tok && MDOC_BLOCK == p->type)
+               if (p->data.Bd)
+                       free(p->data.Bd);
+       if (MDOC_Bl == p->tok && MDOC_BLOCK == p->type)
+               if (p->data.Bl)
+                       free(p->data.Bl);
+       if (MDOC_Bf == p->tok && MDOC_HEAD == p->type)
+               if (p->data.Bf)
+                       free(p->data.Bf);
+
        if (p->string)
                free(p->string);
        if (p->args)
@@ -606,7 +622,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
         */
 
        if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
-                       LIST_column == n->data.Bl.type) {
+                       LIST_column == n->data.Bl->type) {
                /* `Bl' is open without any children. */
                m->flags |= MDOC_FREECOL;
                return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
@@ -615,7 +631,7 @@ mdoc_ptext(struct mdoc *m, int line, char *buf, int offs)
        if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
                        NULL != n->parent &&
                        MDOC_Bl == n->parent->tok &&
-                       LIST_column == n->parent->data.Bl.type) {
+                       LIST_column == n->parent->data.Bl->type) {
                /* `Bl' has block-level `It' children. */
                m->flags |= MDOC_FREECOL;
                return(mdoc_macro(m, MDOC_It, line, offs, &offs, buf));
@@ -727,7 +743,7 @@ macrowarn(struct mdoc *m, int ln, const char *buf, int offs)
  * Parse a macro line, that is, a line beginning with the control
  * character.
  */
-int
+static int
 mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
 {
        enum mdoct        tok;
@@ -821,7 +837,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
         */
 
        if (MDOC_Bl == n->tok && MDOC_BODY == n->type &&
-                       LIST_column == n->data.Bl.type) {
+                       LIST_column == n->data.Bl->type) {
                m->flags |= MDOC_FREECOL;
                if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf))
                        goto err;
@@ -837,7 +853,7 @@ mdoc_pmacro(struct mdoc *m, int ln, char *buf, int offs)
        if (MDOC_It == n->tok && MDOC_BLOCK == n->type &&
                        NULL != n->parent &&
                        MDOC_Bl == n->parent->tok &&
-                       LIST_column == n->parent->data.Bl.type) {
+                       LIST_column == n->parent->data.Bl->type) {
                m->flags |= MDOC_FREECOL;
                if ( ! mdoc_macro(m, MDOC_It, ln, sv, &sv, buf)) 
                        goto err;
index f1d4301..738db79 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc.h,v 1.30 2010/06/29 17:10:29 schwarze Exp $ */
+/*     $Id: mdoc.h,v 1.31 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -252,7 +252,7 @@ struct      mdoc_arg {
 enum   mdoc_endbody {
        ENDBODY_NOT = 0,
        ENDBODY_SPACE,
-       ENDBODY_NOSPACE,
+       ENDBODY_NOSPACE
 };
 
 enum   mdoc_list {
@@ -279,6 +279,19 @@ enum       mdoc_disp {
        DISP_literal
 };
 
+enum   mdoc_auth {
+       AUTH__NONE = 0,
+       AUTH_split,
+       AUTH_nosplit
+};
+
+enum   mdoc_font {
+       FONT__NONE = 0,
+       FONT_Em,
+       FONT_Li,
+       FONT_Sy
+};
+
 struct mdoc_bd {
        const char       *offs; /* -offset */
        enum mdoc_disp    type; /* -ragged, etc. */
@@ -290,6 +303,16 @@ struct     mdoc_bl {
        const char       *offs; /* -offset */
        enum mdoc_list    type; /* -tag, -enum, etc. */
        int               comp; /* -compact */
+       size_t            ncols; /* -column arg count */
+       const char      **cols; /* -column val ptr */
+};
+
+struct mdoc_bf {
+       enum mdoc_font    font; /* font */
+};
+
+struct mdoc_an {
+       enum mdoc_auth    auth; /* -split, etc. */
 };
 
 /* Node in AST. */
@@ -321,8 +344,10 @@ struct     mdoc_node {
        enum mdoc_endbody end;          /* BODY */
 
        union {
-               struct mdoc_bl Bl;
-               struct mdoc_bd Bd;
+               struct mdoc_an  An;
+               struct mdoc_bd *Bd;
+               struct mdoc_bf *Bf;
+               struct mdoc_bl *Bl;
        } data;
 };
 
index 6ce87d3..d6abb75 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc_action.c,v 1.42 2010/07/01 22:31:52 schwarze Exp $ */
+/*     $Id: mdoc_action.c,v 1.43 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include "libmdoc.h"
 #include "libmandoc.h"
 
+/* 
+ * FIXME: this file is deprecated.  All future "actions" should be
+ * pushed into mdoc_validate.c.
+ */
+
 #define        POST_ARGS struct mdoc *m, struct mdoc_node *n
 #define        PRE_ARGS  struct mdoc *m, struct mdoc_node *n
 
@@ -687,7 +692,7 @@ post_bl_tagwidth(POST_ARGS)
        n->args->argv[i].value[0] = mandoc_strdup(buf);
 
        /* Set our width! */
-       n->data.Bl.width = n->args->argv[i].value[0];
+       n->data.Bl->width = n->args->argv[i].value[0];
        return(1);
 }
 
@@ -710,9 +715,9 @@ post_bl_width(POST_ARGS)
         * the macro's width as set in share/tmac/mdoc/doc-common.
         */
 
-       if (0 == strcmp(n->data.Bl.width, "Ds"))
+       if (0 == strcmp(n->data.Bl->width, "Ds"))
                width = 6;
-       else if (MDOC_MAX == (tok = mdoc_hash_find(n->data.Bl.width)))
+       else if (MDOC_MAX == (tok = mdoc_hash_find(n->data.Bl->width)))
                return(1);
        else if (0 == (width = mdoc_macro2len(tok))) 
                return(mdoc_nmsg(m, n, MANDOCERR_BADWIDTH));
@@ -732,7 +737,7 @@ post_bl_width(POST_ARGS)
        n->args->argv[i].value[0] = mandoc_strdup(buf);
 
        /* Set our width! */
-       n->data.Bl.width = n->args->argv[i].value[0];
+       n->data.Bl->width = n->args->argv[i].value[0];
        return(1);
 }
 
@@ -748,7 +753,7 @@ post_bl_head(POST_ARGS)
        int                      i, c;
        struct mdoc_node        *np, *nn, *nnp;
 
-       if (LIST_column != n->data.Bl.type)
+       if (LIST_column != n->data.Bl->type)
                return(1);
        else if (NULL == n->child)
                return(1);
@@ -773,6 +778,9 @@ post_bl_head(POST_ARGS)
        np->args->argv[c].value = mandoc_malloc
                ((size_t)n->nchild * sizeof(char *));
 
+       n->data.Bl->ncols = np->args->argv[c].sz;
+       n->data.Bl->cols = (const char **)np->args->argv[c].value;
+
        for (i = 0, nn = n->child; nn; i++) {
                np->args->argv[c].value[i] = nn->string;
                nn->string = NULL;
@@ -790,8 +798,6 @@ post_bl_head(POST_ARGS)
 static int
 post_bl(POST_ARGS)
 {
-       struct mdoc_node *nn;
-       const char       *ww;
 
        if (MDOC_HEAD == n->type)
                return(post_bl_head(m, n));
@@ -806,28 +812,16 @@ post_bl(POST_ARGS)
         * rewritten into real lengths).
         */
 
-       ww = n->data.Bl.width;
-
-       if (LIST_tag == n->data.Bl.type && NULL == n->data.Bl.width) {
+       if (LIST_tag == n->data.Bl->type && NULL == n->data.Bl->width) {
                if ( ! post_bl_tagwidth(m, n))
                        return(0);
-       } else if (NULL != n->data.Bl.width) {
+       } else if (NULL != n->data.Bl->width) {
                if ( ! post_bl_width(m, n))
                        return(0);
        } else 
                return(1);
 
-       assert(n->data.Bl.width);
-
-       /* If it has changed, propogate new width to children. */
-
-       if (ww == n->data.Bl.width)
-               return(1);
-
-       for (nn = n->child; nn; nn = nn->next)
-               if (MDOC_Bl == nn->tok)
-                       nn->data.Bl.width = n->data.Bl.width;
-
+       assert(n->data.Bl->width);
        return(1);
 }
 
@@ -958,9 +952,10 @@ pre_bd(PRE_ARGS)
        if (MDOC_BODY != n->type)
                return(1);
 
-       if (DISP_literal == n->data.Bd.type)
+       assert(n->data.Bd);
+       if (DISP_literal == n->data.Bd->type)
                m->flags |= MDOC_LITERAL;
-       if (DISP_unfilled == n->data.Bd.type)
+       if (DISP_unfilled == n->data.Bd->type)
                m->flags |= MDOC_LITERAL;
 
        return(1);
index a556aa1..61d5dbb 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc_argv.c,v 1.31 2010/06/26 17:56:43 schwarze Exp $ */
+/*     $Id: mdoc_argv.c,v 1.32 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -355,7 +355,8 @@ mdoc_args(struct mdoc *m, int line, int *pos,
                if (MDOC_Bl == n->tok)
                        break;
 
-       if (n && LIST_column == n->data.Bl.type) {
+       assert(n->data.Bl);
+       if (n && LIST_column == n->data.Bl->type) {
                fl |= ARGS_TABSEP;
                fl &= ~ARGS_DELIM;
        }
index 60e257c..b088164 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc_html.c,v 1.24 2010/06/29 17:10:29 schwarze Exp $ */
+/*     $Id: mdoc_html.c,v 1.25 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -26,7 +26,6 @@
 #include "mandoc.h"
 #include "out.h"
 #include "html.h"
-#include "regs.h"
 #include "mdoc.h"
 #include "main.h"
 
@@ -69,6 +68,8 @@ static        int               mdoc_aq_pre(MDOC_ARGS);
 static int               mdoc_ar_pre(MDOC_ARGS);
 static int               mdoc_bd_pre(MDOC_ARGS);
 static int               mdoc_bf_pre(MDOC_ARGS);
+static void              mdoc_bk_post(MDOC_ARGS);
+static int               mdoc_bk_pre(MDOC_ARGS);
 static void              mdoc_bl_post(MDOC_ARGS);
 static int               mdoc_bl_pre(MDOC_ARGS);
 static void              mdoc_bq_post(MDOC_ARGS);
@@ -233,7 +234,7 @@ static      const struct htmlmdoc mdocs[MDOC_MAX] = {
        {NULL, NULL}, /* Fc */ 
        {mdoc_op_pre, mdoc_op_post}, /* Oo */
        {NULL, NULL}, /* Oc */
-       {NULL, NULL}, /* Bk */
+       {mdoc_bk_pre, mdoc_bk_post}, /* Bk */
        {NULL, NULL}, /* Ek */
        {mdoc_bt_pre, NULL}, /* Bt */
        {NULL, NULL}, /* Hf */
@@ -433,11 +434,23 @@ print_mdoc_node(MDOC_ARGS)
                print_text(h, n->string);
                return;
        default:
-               if (mdocs[n->tok].pre && !n->end)
+               if (mdocs[n->tok].pre && ENDBODY_NOT == n->end)
                        child = (*mdocs[n->tok].pre)(m, n, h);
                break;
        }
 
+       if (HTML_KEEP & h->flags) {
+               if (n->prev && n->prev->line != n->line) {
+                       h->flags &= ~HTML_KEEP;
+                       h->flags |= HTML_PREKEEP;
+               } else if (NULL == n->prev) {
+                       if (n->parent && n->parent->line != n->line) {
+                               h->flags &= ~HTML_KEEP;
+                               h->flags |= HTML_PREKEEP;
+                       }
+               }
+       }
+
        if (child && n->child)
                print_mdoc_nodelist(m, n->child, h);
 
@@ -449,7 +462,7 @@ print_mdoc_node(MDOC_ARGS)
                mdoc_root_post(m, n, h);
                break;
        default:
-               if (mdocs[n->tok].post && !n->end)
+               if (mdocs[n->tok].post && ENDBODY_NOT == n->end)
                        (*mdocs[n->tok].post)(m, n, h);
                break;
        }
@@ -732,17 +745,70 @@ mdoc_op_post(MDOC_ARGS)
 static int
 mdoc_nm_pre(MDOC_ARGS)
 {
-       struct htmlpair tag;
+       struct htmlpair  tag;
+       struct roffsu    su;
+       const char      *cp;
 
-       if (NULL == n->child && NULL == m->name)
-               return(1);
+       /*
+        * Accomodate for `Nm' being both an element (which may have
+        * NULL children AND no m->name) and a block.
+        */
 
-       synopsis_pre(h, n);
+       cp = NULL;
+
+       if (MDOC_ELEM == n->type) {
+               if (NULL == n->child && NULL == m->name)
+                       return(1);
+               synopsis_pre(h, n);
+               PAIR_CLASS_INIT(&tag, "name");
+               print_otag(h, TAG_SPAN, 1, &tag);
+               if (NULL == n->child)
+                       print_text(h, m->name);
+       } else if (MDOC_BLOCK == n->type) {
+               synopsis_pre(h, n);
+
+               bufcat_style(h, "clear", "both");
+               if (n->head->child || m->name) {
+                       if (n->head->child && MDOC_TEXT == 
+                                       n->head->child->type)
+                               cp = n->head->child->string;
+                       if (NULL == cp || '\0' == *cp)
+                               cp = m->name;
+
+                       SCALE_HS_INIT(&su, (double)strlen(cp));
+                       bufcat_su(h, "padding-left", &su);
+               }
+
+               PAIR_STYLE_INIT(&tag, h);
+               print_otag(h, TAG_DIV, 1, &tag);
+       } else if (MDOC_HEAD == n->type) { 
+               if (NULL == n->child && NULL == m->name)
+                       return(1);
+
+               if (n->child && MDOC_TEXT == n->child->type)
+                       cp = n->child->string;
+               if (NULL == cp || '\0' == *cp)
+                       cp = m->name;
+
+               SCALE_HS_INIT(&su, (double)strlen(cp));
+
+               bufcat_style(h, "float", "left");
+               bufcat_su(h, "min-width", &su);
+               SCALE_INVERT(&su);
+               bufcat_su(h, "margin-left", &su);
+
+               PAIR_STYLE_INIT(&tag, h);
+               print_otag(h, TAG_DIV, 1, &tag);
+
+               if (NULL == n->child)
+                       print_text(h, m->name);
+       } else if (MDOC_BODY == n->type) {
+               SCALE_HS_INIT(&su, 2);
+               bufcat_su(h, "margin-left", &su);
+               PAIR_STYLE_INIT(&tag, h);
+               print_otag(h, TAG_DIV, 1, &tag);
+       }
 
-       PAIR_CLASS_INIT(&tag, "name");
-       print_otag(h, TAG_SPAN, 1, &tag);
-       if (NULL == n->child)
-               print_text(h, m->name);
        return(1);
 }
 
@@ -1017,7 +1083,7 @@ mdoc_it_head_pre(MDOC_ARGS, enum mdoc_list type, struct roffsu *width)
 static int
 mdoc_it_pre(MDOC_ARGS)
 {
-       int                      i, wp, comp;
+       int                      i, comp;
        const struct mdoc_node  *bl, *nn;
        struct roffsu            width, offs;
        enum mdoc_list           type;
@@ -1034,11 +1100,12 @@ mdoc_it_pre(MDOC_ARGS)
 
        SCALE_HS_INIT(&offs, 0);
 
-       type = bl->data.Bl.type;
-       comp = bl->data.Bl.comp;
+       assert(bl->data.Bl);
+       type = bl->data.Bl->type;
+       comp = bl->data.Bl->comp;
 
-       if (bl->data.Bl.offs)
-               a2offs(bl->data.Bl.offs, &offs);
+       if (bl->data.Bl->offs)
+               a2offs(bl->data.Bl->offs, &offs);
 
        switch (type) {
        case (LIST_enum):
@@ -1055,18 +1122,8 @@ mdoc_it_pre(MDOC_ARGS)
                break;
        }
 
-       if (bl->data.Bl.width)
-               a2width(bl->data.Bl.width, &width);
-
-       wp = -1;
-       for (i = 0; bl->args && i < (int)bl->args->argc; i++) 
-               switch (bl->args->argv[i].arg) {
-               case (MDOC_Column):
-                       wp = i; /* Save for later. */
-                       break;
-               default:
-                       break;
-               }
+       if (bl->data.Bl->width)
+               a2width(bl->data.Bl->width, &width);
 
        /* Override width in some cases. */
 
@@ -1091,8 +1148,8 @@ mdoc_it_pre(MDOC_ARGS)
                for (i = 0; nn && nn != n; nn = nn->next)
                        if (MDOC_BODY == nn->type)
                                i++;
-               if (i < (int)bl->args->argv[wp].sz)
-                       a2width(bl->args->argv[wp].value[i], &width);
+               if (i < (int)bl->data.Bl->ncols)
+                       a2width(bl->data.Bl->cols[i], &width);
        }
 
        if (MDOC_HEAD == n->type)
@@ -1114,7 +1171,8 @@ mdoc_bl_pre(MDOC_ARGS)
                return(0);
        if (MDOC_BLOCK != n->type)
                return(1);
-       if (LIST_enum != n->data.Bl.type)
+       assert(n->data.Bl);
+       if (LIST_enum != n->data.Bl->type)
                return(1);
 
        ord = malloc(sizeof(struct ord));
@@ -1138,7 +1196,7 @@ mdoc_bl_post(MDOC_ARGS)
 
        if (MDOC_BLOCK != n->type)
                return;
-       if (LIST_enum != n->data.Bl.type)
+       if (LIST_enum != n->data.Bl->type)
                return;
 
        ord = h->ords.head;
@@ -1353,10 +1411,11 @@ mdoc_bd_pre(MDOC_ARGS)
 
        SCALE_VS_INIT(&su, 0);
 
-       if (n->data.Bd.offs)
-               a2offs(n->data.Bd.offs, &su);
+       assert(n->data.Bd);
+       if (n->data.Bd->offs)
+               a2offs(n->data.Bd->offs, &su);
 
-       comp = n->data.Bd.comp;
+       comp = n->data.Bd->comp;
 
        /* FIXME: -centered, etc. formatting. */
        /* FIXME: does not respect -offset ??? */
@@ -1383,8 +1442,8 @@ mdoc_bd_pre(MDOC_ARGS)
                return(1);
        }
 
-       if (DISP_unfilled != n->data.Bd.type && 
-                       DISP_literal != n->data.Bd.type)
+       if (DISP_unfilled != n->data.Bd->type && 
+                       DISP_literal != n->data.Bd->type)
                return(1);
 
        PAIR_CLASS_INIT(&tag[0], "lit");
@@ -1955,46 +2014,33 @@ mdoc_ap_pre(MDOC_ARGS)
 static int
 mdoc_bf_pre(MDOC_ARGS)
 {
-       int              i;
        struct htmlpair  tag[2];
        struct roffsu    su;
 
        if (MDOC_HEAD == n->type)
                return(0);
-       else if (MDOC_BLOCK != n->type)
+       else if (MDOC_BODY != n->type)
                return(1);
 
-       PAIR_CLASS_INIT(&tag[0], "lit");
-
-       if (n->head->child) {
-               if ( ! strcmp("Em", n->head->child->string))
-                       PAIR_CLASS_INIT(&tag[0], "emph");
-               else if ( ! strcmp("Sy", n->head->child->string))
-                       PAIR_CLASS_INIT(&tag[0], "symb");
-               else if ( ! strcmp("Li", n->head->child->string))
-                       PAIR_CLASS_INIT(&tag[0], "lit");
-       } else {
-               for (i = 0; n->args && i < (int)n->args->argc; i++) 
-                       switch (n->args->argv[i].arg) {
-                       case (MDOC_Symbolic):
-                               PAIR_CLASS_INIT(&tag[0], "symb");
-                               break;
-                       case (MDOC_Literal):
-                               PAIR_CLASS_INIT(&tag[0], "lit");
-                               break;
-                       case (MDOC_Emphasis):
-                               PAIR_CLASS_INIT(&tag[0], "emph");
-                               break;
-                       default:
-                               break;
-                       }
-       }
+       assert(n->data.Bf);
 
-       /* FIXME: div's have spaces stripped--we want them. */
+       if (FONT_Em == n->data.Bf->font) 
+               PAIR_CLASS_INIT(&tag[0], "emph");
+       else if (FONT_Sy == n->data.Bf->font) 
+               PAIR_CLASS_INIT(&tag[0], "symb");
+       else if (FONT_Li == n->data.Bf->font) 
+               PAIR_CLASS_INIT(&tag[0], "lit");
+       else
+               PAIR_CLASS_INIT(&tag[0], "none");
 
+       /* 
+        * We want this to be inline-formatted, but needs to be div to
+        * accept block children. 
+        */
        bufcat_style(h, "display", "inline");
        SCALE_HS_INIT(&su, 1);
-       bufcat_su(h, "margin-right", &su);
+       /* Needs a left-margin for spacing. */
+       bufcat_su(h, "margin-left", &su);
        PAIR_STYLE_INIT(&tag[1], h);
        print_otag(h, TAG_DIV, 2, tag);
        return(1);
@@ -2190,3 +2236,35 @@ mdoc__x_post(MDOC_ARGS)
        h->flags |= HTML_NOSPACE;
        print_text(h, n->next ? "," : ".");
 }
+
+
+/* ARGSUSED */
+static int
+mdoc_bk_pre(MDOC_ARGS)
+{
+
+       switch (n->type) {
+       case (MDOC_BLOCK):
+               break;
+       case (MDOC_HEAD):
+               return(0);
+       case (MDOC_BODY):
+               h->flags |= HTML_PREKEEP;
+               break;
+       default:
+               abort();
+               /* NOTREACHED */
+       }
+
+       return(1);
+}
+
+
+/* ARGSUSED */
+static void
+mdoc_bk_post(MDOC_ARGS)
+{
+
+       if (MDOC_BODY == n->type)
+               h->flags &= ~(HTML_KEEP | HTML_PREKEEP);
+}
index acaee57..c145394 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: mdoc_macro.c,v 1.53 2010/07/01 22:31:52 schwarze Exp $ */
+/*     $Id: mdoc_macro.c,v 1.54 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 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
@@ -30,7 +31,7 @@ enum  rew {   /* see rew_dohalt() */
        REWIND_THIS,
        REWIND_MORE,
        REWIND_LATER,
-       REWIND_ERROR,
+       REWIND_ERROR
 };
 
 static int             blk_full(MACRO_PROT_ARGS);
@@ -410,7 +411,7 @@ rew_dohalt(enum mdoct tok, enum mdoc_type type,
         * In particular, always skip block end markers,
         * and let all blocks rewind Nm children.
         */
-       if (p->end || MDOC_Nm == p->tok ||
+       if (ENDBODY_NOT != p->end || MDOC_Nm == p->tok ||
            (MDOC_BLOCK == p->type &&
            ! (MDOC_EXPLICIT & mdoc_macros[tok].flags)))
                return(REWIND_MORE);
@@ -566,6 +567,7 @@ rew_sub(enum mdoc_type t, struct mdoc *m,
                    ! mdoc_body_alloc(m, n->line, n->pos, n->tok))
                        return(0);
        }
+
        return(1);
 }
 
@@ -650,7 +652,7 @@ blk_exp_close(MACRO_PROT_ARGS)
 
                /* Remember the start of our own body. */
                if (MDOC_BODY == n->type && atok == n->tok) {
-                       if ( ! n->end)
+                       if (ENDBODY_NOT == n->end)
                                body = n;
                        continue;
                }
@@ -1146,6 +1148,7 @@ blk_full(MACRO_PROT_ARGS)
                        return(1);
                }
        }
+
        /* Close out scopes to remain in a consistent state. */
 
        if ( ! rew_sub(MDOC_HEAD, m, tok, line, ppos))
index 90c6fde..acb170d 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: mdoc_term.c,v 1.94 2010/07/01 15:36:59 schwarze Exp $ */
+/*     $Id: mdoc_term.c,v 1.95 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 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
@@ -26,7 +27,6 @@
 #include "mandoc.h"
 #include "out.h"
 #include "term.h"
-#include "regs.h"
 #include "mdoc.h"
 #include "chars.h"
 #include "main.h"
@@ -53,8 +53,6 @@ static        size_t    a2width(const struct termp *, const char *);
 static size_t    a2height(const struct termp *, const char *);
 static size_t    a2offs(const struct termp *, const char *);
 
-static int       arg_hasattr(int, const struct mdoc_node *);
-static int       arg_getattr(int, const struct mdoc_node *);
 static void      print_bvspace(struct termp *,
                        const struct mdoc_node *,
                        const struct mdoc_node *);
@@ -324,25 +322,41 @@ print_mdoc_node(DECL_ARGS)
 
        if (MDOC_TEXT == n->type)
                term_word(p, n->string); 
-       else if (termacts[n->tok].pre && !n->end)
+       else if (termacts[n->tok].pre && ENDBODY_NOT == n->end)
                chld = (*termacts[n->tok].pre)(p, &npair, m, n);
 
+       /*
+        * Keeps only work until the end of a line.  If a keep was
+        * invoked in a prior line, revert it to PREKEEP.
+        */
+
+       if (TERMP_KEEP & p->flags) {
+               if (n->prev && n->prev->line != n->line) {
+                       p->flags &= ~TERMP_KEEP;
+                       p->flags |= TERMP_PREKEEP;
+               } else if (NULL == n->prev) {
+                       if (n->parent && n->parent->line != n->line) {
+                               p->flags &= ~TERMP_KEEP;
+                               p->flags |= TERMP_PREKEEP;
+                       }
+               }
+       }
+
        if (chld && n->child)
                print_mdoc_nodelist(p, &npair, m, n->child);
 
        term_fontpopq(p, font);
 
-       if (MDOC_TEXT != n->type &&
-           termacts[n->tok].post &&
-           ! (MDOC_ENDED & n->flags)) {
-               (*termacts[n->tok].post)(p, &npair, m, n);
+       if (MDOC_TEXT != n->type && termacts[n->tok].post && 
+                       ! (MDOC_ENDED & n->flags)) {
+               (void)(*termacts[n->tok].post)(p, &npair, m, n);
 
                /*
                 * Explicit end tokens not only call the post
                 * handler, but also tell the respective block
                 * that it must not call the post handler again.
                 */
-               if (n->end)
+               if (ENDBODY_NOT != n->end)
                        n->pending->flags |= MDOC_ENDED;
 
                /*
@@ -524,38 +538,6 @@ a2offs(const struct termp *p, const char *v)
 }
 
 
-/*
- * Return 1 if an argument has a particular argument value or 0 if it
- * does not.  See arg_getattr().
- */
-static int
-arg_hasattr(int arg, const struct mdoc_node *n)
-{
-
-       return(-1 != arg_getattr(arg, n));
-}
-
-
-/*
- * Get the index of an argument in a node's argument list or -1 if it
- * does not exist.
- */
-static int
-arg_getattr(int v, const struct mdoc_node *n)
-{
-       int              i;
-
-       if (NULL == n->args)
-               return(0);
-
-       for (i = 0; i < (int)n->args->argc; i++) 
-               if (n->args->argv[i].arg == v)
-                       return(i);
-
-       return(-1);
-}
-
-
 /*
  * Determine how much space to print out before block elements of `It'
  * (and thus `Bl') and `Bd'.  And then go ahead and print that space,
@@ -570,9 +552,9 @@ print_bvspace(struct termp *p,
 
        term_newln(p);
 
-       if (MDOC_Bd == bl->tok && bl->data.Bd.comp)
+       if (MDOC_Bd == bl->tok && bl->data.Bd->comp)
                return;
-       if (MDOC_Bl == bl->tok && bl->data.Bl.comp)
+       if (MDOC_Bl == bl->tok && bl->data.Bl->comp)
                return;
 
        /* Do not vspace directly after Ss/Sh. */
@@ -591,13 +573,13 @@ print_bvspace(struct termp *p,
 
        /* A `-column' does not assert vspace within the list. */
 
-       if (MDOC_Bl == bl->tok && LIST_column == bl->data.Bl.type)
+       if (MDOC_Bl == bl->tok && LIST_column == bl->data.Bl->type)
                if (n->prev && MDOC_It == n->prev->tok)
                        return;
 
        /* A `-diag' without body does not vspace. */
 
-       if (MDOC_Bl == bl->tok && LIST_diag == bl->data.Bl.type)
+       if (MDOC_Bl == bl->tok && LIST_diag == bl->data.Bl->type)
                if (n->prev && MDOC_It == n->prev->tok) {
                        assert(n->prev->body);
                        if (NULL == n->prev->body->child)
@@ -641,7 +623,7 @@ termp_it_pre(DECL_ARGS)
 {
        const struct mdoc_node *bl, *nn;
        char                    buf[7];
-       int                     i, col;
+       int                     i;
        size_t                  width, offset, ncols, dcol;
        enum mdoc_list          type;
 
@@ -651,7 +633,8 @@ termp_it_pre(DECL_ARGS)
        }
 
        bl = n->parent->parent->parent;
-       type = bl->data.Bl.type;
+       assert(bl->data.Bl);
+       type = bl->data.Bl->type;
 
        /* 
         * First calculate width and offset.  This is pretty easy unless
@@ -661,16 +644,14 @@ termp_it_pre(DECL_ARGS)
 
        width = offset = 0;
 
-       if (bl->data.Bl.offs)
-               offset = a2offs(p, bl->data.Bl.offs);
+       if (bl->data.Bl->offs)
+               offset = a2offs(p, bl->data.Bl->offs);
 
        switch (type) {
        case (LIST_column):
                if (MDOC_HEAD == n->type)
                        break;
 
-               col = arg_getattr(MDOC_Column, bl);
-
                /*
                 * Imitate groff's column handling:
                 * - For each earlier column, add its width.
@@ -680,7 +661,8 @@ termp_it_pre(DECL_ARGS)
                 *   column.
                 * - For more than 5 columns, add only one column.
                 */
-               ncols = bl->args->argv[col].sz;
+               ncols = bl->data.Bl->ncols;
+
                /* LINTED */
                dcol = ncols < 5 ? term_len(p, 4) : 
                        ncols == 5 ? term_len(p, 3) : term_len(p, 1);
@@ -694,7 +676,7 @@ termp_it_pre(DECL_ARGS)
                                nn->prev && i < (int)ncols; 
                                nn = nn->prev, i++)
                        offset += dcol + a2width
-                               (p, bl->args->argv[col].value[i]);
+                               (p, bl->data.Bl->cols[i]);
 
                /*
                 * When exceeding the declared number of columns, leave
@@ -709,10 +691,10 @@ termp_it_pre(DECL_ARGS)
                 * Use the declared column widths, extended as explained
                 * in the preceding paragraph.
                 */
-               width = a2width(p, bl->args->argv[col].value[i]) + dcol;
+               width = a2width(p, bl->data.Bl->cols[i]) + dcol;
                break;
        default:
-               if (NULL == bl->data.Bl.width)
+               if (NULL == bl->data.Bl->width)
                        break;
 
                /* 
@@ -720,8 +702,8 @@ termp_it_pre(DECL_ARGS)
                 * number for buffering single arguments.  See the above
                 * handling for column for how this changes.
                 */
-               assert(bl->data.Bl.width);
-               width = a2width(p, bl->data.Bl.width) + term_len(p, 2);
+               assert(bl->data.Bl->width);
+               width = a2width(p, bl->data.Bl->width) + term_len(p, 2);
                break;
        }
 
@@ -983,7 +965,7 @@ termp_it_post(DECL_ARGS)
        if (MDOC_BLOCK == n->type)
                return;
 
-       type = n->parent->parent->parent->data.Bl.type;
+       type = n->parent->parent->parent->data.Bl->type;
 
        switch (type) {
        case (LIST_item):
@@ -1137,10 +1119,10 @@ termp_an_post(DECL_ARGS)
                return;
        }
 
-       if (arg_hasattr(MDOC_Split, n)) {
+       if (AUTH_split == n->data.An.auth) {
                p->flags &= ~TERMP_NOSPLIT;
                p->flags |= TERMP_SPLIT;
-       } else {
+       } else if (AUTH_nosplit == n->data.An.auth) {
                p->flags &= ~TERMP_SPLIT;
                p->flags |= TERMP_NOSPLIT;
        }
@@ -1644,8 +1626,9 @@ termp_bd_pre(DECL_ARGS)
        } else if (MDOC_HEAD == n->type)
                return(0);
 
-       if (n->data.Bd.offs)
-               p->offset += a2offs(p, n->data.Bd.offs);
+       assert(n->data.Bd);
+       if (n->data.Bd->offs)
+               p->offset += a2offs(p, n->data.Bd->offs);
 
        /*
         * If -ragged or -filled are specified, the block does nothing
@@ -1655,8 +1638,8 @@ termp_bd_pre(DECL_ARGS)
         * lines are allowed.
         */
        
-       if (DISP_literal != n->data.Bd.type && 
-                       DISP_unfilled != n->data.Bd.type)
+       if (DISP_literal != n->data.Bd->type && 
+                       DISP_unfilled != n->data.Bd->type)
                return(1);
 
        tabwidth = p->tabwidth;
@@ -1693,8 +1676,9 @@ termp_bd_post(DECL_ARGS)
        rm = p->rmargin;
        rmax = p->maxrmargin;
 
-       if (DISP_literal == n->data.Bd.type || 
-                       DISP_unfilled == n->data.Bd.type)
+       assert(n->data.Bd);
+       if (DISP_literal == n->data.Bd->type || 
+                       DISP_unfilled == n->data.Bd->type)
                p->rmargin = p->maxrmargin = TERM_MAXMARGIN;
 
        p->flags |= TERMP_NOSPACE;
@@ -2019,9 +2003,11 @@ termp_fo_pre(DECL_ARGS)
                return(1);
        } 
 
+       if (NULL == n->child)
+               return(0);
+
        /* XXX: we drop non-initial arguments as per groff. */
 
-       assert(n->child);
        assert(n->child->string);
        term_fontpush(p, TERMFONT_BOLD);
        term_word(p, n->child->string);
@@ -2051,30 +2037,19 @@ termp_fo_post(DECL_ARGS)
 static int
 termp_bf_pre(DECL_ARGS)
 {
-       const struct mdoc_node  *nn;
 
        if (MDOC_HEAD == n->type)
                return(0);
        else if (MDOC_BLOCK != n->type)
                return(1);
 
-       if (NULL == (nn = n->head->child)) {
-               if (arg_hasattr(MDOC_Emphasis, n))
-                       term_fontpush(p, TERMFONT_UNDER);
-               else if (arg_hasattr(MDOC_Symbolic, n))
-                       term_fontpush(p, TERMFONT_BOLD);
-               else
-                       term_fontpush(p, TERMFONT_NONE);
-
-               return(1);
-       } 
+       assert(n->data.Bf);
 
-       assert(MDOC_TEXT == nn->type);
-       if (0 == strcmp("Em", nn->string))
+       if (FONT_Em == n->data.Bf->font) 
                term_fontpush(p, TERMFONT_UNDER);
-       else if (0 == strcmp("Sy", nn->string))
+       else if (FONT_Sy == n->data.Bf->font) 
                term_fontpush(p, TERMFONT_BOLD);
-       else
+       else 
                term_fontpush(p, TERMFONT_NONE);
 
        return(1);
@@ -2164,15 +2139,18 @@ termp_bk_pre(DECL_ARGS)
 
        switch (n->type) {
        case (MDOC_BLOCK):
-               return(1);
+               break;
        case (MDOC_HEAD):
                return(0);
        case (MDOC_BODY):
                p->flags |= TERMP_PREKEEP;
-               return(1);
+               break;
        default:
                abort();
+               /* NOTREACHED */
        }
+
+       return(1);
 }
 
 
index bdd143a..2b1fc08 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: mdoc_validate.c,v 1.64 2010/07/02 17:41:05 schwarze Exp $ */
+/*     $Id: mdoc_validate.c,v 1.65 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -150,7 +150,7 @@ const       struct valids mdoc_valids[MDOC_MAX] = {
        { NULL, posts_notext },                 /* Pp */ 
        { pres_d1, posts_wline },               /* D1 */
        { pres_d1, posts_wline },               /* Dl */
-       { pres_bd, posts_bd_bk },                       /* Bd */
+       { pres_bd, posts_bd_bk },               /* Bd */
        { NULL, NULL },                         /* Ed */
        { pres_bl, posts_bl },                  /* Bl */ 
        { NULL, NULL },                         /* El */
@@ -454,6 +454,11 @@ check_text(struct mdoc *mdoc, int line, int pos, char *p)
 {
        int              c;
 
+       /* 
+        * FIXME: we absolutely cannot let \b get through or it will
+        * destroy some assumptions in terms of format.
+        */
+
        for ( ; *p; p++, pos++) {
                if ('\t' == *p) {
                        if ( ! (MDOC_LITERAL & mdoc->flags))
@@ -528,17 +533,23 @@ pre_display(PRE_ARGS)
 static int
 pre_bl(PRE_ARGS)
 {
-       int              i, comp, dup;
-       const char      *offs, *width;
-       enum mdoc_list   lt;
+       int               i, comp, dup;
+       const char       *offs, *width;
+       enum mdoc_list    lt;
+       struct mdoc_node *np;
 
        if (MDOC_BLOCK != n->type) {
-               assert(n->parent);
-               assert(MDOC_BLOCK == n->parent->type);
-               assert(MDOC_Bl == n->parent->tok);
-               assert(LIST__NONE != n->parent->data.Bl.type);
-               memcpy(&n->data.Bl, &n->parent->data.Bl,
-                               sizeof(struct mdoc_bl));
+               if (ENDBODY_NOT != n->end) {
+                       assert(n->pending);
+                       np = n->pending->parent;
+               } else
+                       np = n->parent;
+
+               assert(np);
+               assert(MDOC_BLOCK == np->type);
+               assert(MDOC_Bl == np->tok);
+               assert(np->data.Bl);
+               n->data.Bl = np->data.Bl;
                return(1);
        }
 
@@ -548,7 +559,8 @@ pre_bl(PRE_ARGS)
         * ones.  If we find no list type, we default to LIST_item.
         */
 
-       assert(LIST__NONE == n->data.Bl.type);
+       assert(NULL == n->data.Bl);
+       n->data.Bl = mandoc_calloc(1, sizeof(struct mdoc_bl));
 
        /* LINTED */
        for (i = 0; n->args && i < (int)n->args->argc; i++) {
@@ -592,18 +604,18 @@ pre_bl(PRE_ARGS)
                        break;
                /* Set list arguments. */
                case (MDOC_Compact):
-                       dup = n->data.Bl.comp;
+                       dup = n->data.Bl->comp;
                        comp = 1;
                        break;
                case (MDOC_Width):
-                       dup = (NULL != n->data.Bl.width);
+                       dup = (NULL != n->data.Bl->width);
                        width = n->args->argv[i].value[0];
                        break;
                case (MDOC_Offset):
                        /* NB: this can be empty! */
                        if (n->args->argv[i].sz) {
                                offs = n->args->argv[i].value[0];
-                               dup = (NULL != n->data.Bl.offs);
+                               dup = (NULL != n->data.Bl->offs);
                                break;
                        }
                        if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV))
@@ -617,29 +629,37 @@ pre_bl(PRE_ARGS)
                        return(0);
 
                if (comp && ! dup)
-                       n->data.Bl.comp = comp;
+                       n->data.Bl->comp = comp;
                if (offs && ! dup)
-                       n->data.Bl.offs = offs;
+                       n->data.Bl->offs = offs;
                if (width && ! dup)
-                       n->data.Bl.width = width;
+                       n->data.Bl->width = width;
 
                /* Check: multiple list types. */
 
-               if (LIST__NONE != lt && n->data.Bl.type != LIST__NONE)
+               if (LIST__NONE != lt && n->data.Bl->type != LIST__NONE)
                        if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTREP))
                                return(0);
 
                /* Assign list type. */
 
-               if (LIST__NONE != lt && n->data.Bl.type == LIST__NONE)
-                       n->data.Bl.type = lt;
+               if (LIST__NONE != lt && n->data.Bl->type == LIST__NONE) {
+                       n->data.Bl->type = lt;
+                       /* Set column information, too. */
+                       if (LIST_column == lt) {
+                               n->data.Bl->ncols = 
+                                       n->args->argv[i].sz;
+                               n->data.Bl->cols = (const char **)
+                                       n->args->argv[i].value;
+                       }
+               }
 
                /* The list type should come first. */
 
-               if (n->data.Bl.type == LIST__NONE)
-                       if (n->data.Bl.width || 
-                                       n->data.Bl.offs || 
-                                       n->data.Bl.comp)
+               if (n->data.Bl->type == LIST__NONE)
+                       if (n->data.Bl->width || 
+                                       n->data.Bl->offs || 
+                                       n->data.Bl->comp)
                                if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTFIRST))
                                        return(0);
 
@@ -648,10 +668,10 @@ pre_bl(PRE_ARGS)
 
        /* Allow lists to default to LIST_item. */
 
-       if (LIST__NONE == n->data.Bl.type) {
+       if (LIST__NONE == n->data.Bl->type) {
                if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_LISTTYPE))
                        return(0);
-               n->data.Bl.type = LIST_item;
+               n->data.Bl->type = LIST_item;
        }
 
        /* 
@@ -660,9 +680,9 @@ pre_bl(PRE_ARGS)
         * and must also be warned.
         */
 
-       switch (n->data.Bl.type) {
+       switch (n->data.Bl->type) {
        case (LIST_tag):
-               if (n->data.Bl.width)
+               if (n->data.Bl->width)
                        break;
                if (mdoc_nmsg(mdoc, n, MANDOCERR_NOWIDTHARG))
                        break;
@@ -676,7 +696,7 @@ pre_bl(PRE_ARGS)
        case (LIST_inset):
                /* FALLTHROUGH */
        case (LIST_item):
-               if (NULL == n->data.Bl.width)
+               if (NULL == n->data.Bl->width)
                        break;
                if (mdoc_nmsg(mdoc, n, MANDOCERR_WIDTHARG))
                        break;
@@ -692,21 +712,28 @@ pre_bl(PRE_ARGS)
 static int
 pre_bd(PRE_ARGS)
 {
-       int              i, dup, comp;
-       enum mdoc_disp   dt;
-       const char      *offs;
+       int               i, dup, comp;
+       enum mdoc_disp    dt;
+       const char       *offs;
+       struct mdoc_node *np;
 
        if (MDOC_BLOCK != n->type) {
-               assert(n->parent);
-               assert(MDOC_BLOCK == n->parent->type);
-               assert(MDOC_Bd == n->parent->tok);
-               assert(DISP__NONE != n->parent->data.Bd.type);
-               memcpy(&n->data.Bd, &n->parent->data.Bd, 
-                               sizeof(struct mdoc_bd));
+               if (ENDBODY_NOT != n->end) {
+                       assert(n->pending);
+                       np = n->pending->parent;
+               } else
+                       np = n->parent;
+
+               assert(np);
+               assert(MDOC_BLOCK == np->type);
+               assert(MDOC_Bd == np->tok);
+               assert(np->data.Bd);
+               n->data.Bd = np->data.Bd;
                return(1);
        }
 
-       assert(DISP__NONE == n->data.Bd.type);
+       assert(NULL == n->data.Bd);
+       n->data.Bd = mandoc_calloc(1, sizeof(struct mdoc_bd));
 
        /* LINTED */
        for (i = 0; n->args && i < (int)n->args->argc; i++) {
@@ -737,7 +764,7 @@ pre_bd(PRE_ARGS)
                        /* NB: this can be empty! */
                        if (n->args->argv[i].sz) {
                                offs = n->args->argv[i].value[0];
-                               dup = (NULL != n->data.Bd.offs);
+                               dup = (NULL != n->data.Bd->offs);
                                break;
                        }
                        if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV))
@@ -745,7 +772,7 @@ pre_bd(PRE_ARGS)
                        break;
                case (MDOC_Compact):
                        comp = 1;
-                       dup = n->data.Bd.comp;
+                       dup = n->data.Bd->comp;
                        break;
                default:
                        abort();
@@ -760,26 +787,26 @@ pre_bd(PRE_ARGS)
                /* Make our auxiliary assignments. */
 
                if (offs && ! dup)
-                       n->data.Bd.offs = offs;
+                       n->data.Bd->offs = offs;
                if (comp && ! dup)
-                       n->data.Bd.comp = comp;
+                       n->data.Bd->comp = comp;
 
                /* Check whether a type has already been assigned. */
 
-               if (DISP__NONE != dt && n->data.Bd.type != DISP__NONE)
+               if (DISP__NONE != dt && n->data.Bd->type != DISP__NONE)
                        if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPREP))
                                return(0);
 
                /* Make our type assignment. */
 
-               if (DISP__NONE != dt && n->data.Bd.type == DISP__NONE)
-                       n->data.Bd.type = dt;
+               if (DISP__NONE != dt && n->data.Bd->type == DISP__NONE)
+                       n->data.Bd->type = dt;
        }
 
-       if (DISP__NONE == n->data.Bd.type) {
+       if (DISP__NONE == n->data.Bd->type) {
                if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_DISPTYPE))
                        return(0);
-               n->data.Bd.type = DISP_ragged;
+               n->data.Bd->type = DISP_ragged;
        }
 
        return(1);
@@ -826,13 +853,20 @@ static int
 pre_an(PRE_ARGS)
 {
 
-       if (NULL == n->args || 1 == n->args->argc)
+       if (NULL == n->args)
                return(1);
-       mdoc_vmsg(mdoc, MANDOCERR_SYNTARGCOUNT, 
-                               n->line, n->pos,
-                               "line arguments == 1 (have %d)",
-                               n->args->argc);
-       return(0);
+       if (n->args->argc > 1)
+               if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_ARGCOUNT))
+                       return(0);
+
+       if (MDOC_Split == n->args->argv[0].arg)
+               n->data.An.auth = AUTH_split;
+       else if (MDOC_Nosplit == n->args->argv[0].arg)
+               n->data.An.auth = AUTH_nosplit;
+       else
+               abort();
+
+       return(1);
 }
 
 
@@ -908,38 +942,74 @@ pre_dd(PRE_ARGS)
 static int
 post_bf(POST_ARGS)
 {
-       char             *p;
-       struct mdoc_node *head;
+       struct mdoc_node *np;
+       int               arg;
 
-       if (MDOC_BLOCK != mdoc->last->type)
+       /*
+        * Unlike other data pointers, these are "housed" by the HEAD
+        * element, which contains the goods.
+        */
+
+       if (MDOC_HEAD != mdoc->last->type) {
+               if (ENDBODY_NOT != mdoc->last->end) {
+                       assert(mdoc->last->pending);
+                       np = mdoc->last->pending->parent->head;
+               } else if (MDOC_BLOCK != mdoc->last->type) {
+                       np = mdoc->last->parent->head;
+               } else 
+                       np = mdoc->last->head;
+
+               assert(np);
+               assert(MDOC_HEAD == np->type);
+               assert(MDOC_Bf == np->tok);
+               assert(np->data.Bf);
+               mdoc->last->data.Bf = np->data.Bf;
                return(1);
+       }
 
-       head = mdoc->last->head;
+       np = mdoc->last;
+       assert(MDOC_BLOCK == np->parent->type);
+       assert(MDOC_Bf == np->parent->tok);
+       np->data.Bf = mandoc_calloc(1, sizeof(struct mdoc_bf));
 
-       if (mdoc->last->args && head->child) {
-               /* FIXME: this should provide a default. */
-               mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SYNTARGVCOUNT);
-               return(0);
-       } else if (mdoc->last->args)
-               return(1);
+       /* 
+        * Cannot have both argument and parameter.
+        * If neither is specified, let it through with a warning. 
+        */
 
-       if (NULL == head->child || MDOC_TEXT != head->child->type) {
-               /* FIXME: this should provide a default. */
-               mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_SYNTARGVCOUNT);
+       if (np->parent->args && np->child) {
+               mdoc_nmsg(mdoc, np, MANDOCERR_SYNTARGVCOUNT);
                return(0);
+       } else if (NULL == np->parent->args && NULL == np->child)
+               return(mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE));
+
+       /* Extract argument into data. */
+       
+       if (np->parent->args) {
+               arg = np->parent->args->argv[0].arg;
+               if (MDOC_Emphasis == arg)
+                       np->data.Bf->font = FONT_Em;
+               else if (MDOC_Literal == arg)
+                       np->data.Bf->font = FONT_Li;
+               else if (MDOC_Symbolic == arg)
+                       np->data.Bf->font = FONT_Sy;
+               else
+                       abort();
+               return(1);
        }
 
-       p = head->child->string;
+       /* Extract parameter into data. */
 
-       if (0 == strcmp(p, "Em"))
-               return(1);
-       else if (0 == strcmp(p, "Li"))
-               return(1);
-       else if (0 == strcmp(p, "Sy"))
-               return(1);
+       if (0 == strcmp(np->child->string, "Em"))
+               np->data.Bf->font = FONT_Em;
+       else if (0 == strcmp(np->child->string, "Li"))
+               np->data.Bf->font = FONT_Li;
+       else if (0 == strcmp(np->child->string, "Sy"))
+               np->data.Bf->font = FONT_Sy;
+       else if ( ! mdoc_nmsg(mdoc, np, MANDOCERR_FONTTYPE))
+               return(0);
 
-       mdoc_nmsg(mdoc, head, MANDOCERR_FONTTYPE);
-       return(0);
+       return(1);
 }
 
 
@@ -1017,16 +1087,14 @@ post_at(POST_ARGS)
 static int
 post_an(POST_ARGS)
 {
+       struct mdoc_node *np;
 
-       if (mdoc->last->args) {
-               if (NULL == mdoc->last->child)
-                       return(1);
-               return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_ARGCOUNT));
-       }
-
-       if (mdoc->last->child)
+       np = mdoc->last;
+       if (AUTH__NONE != np->data.An.auth && np->child)
+               return(mdoc_nmsg(mdoc, np, MANDOCERR_ARGCOUNT));
+       if (AUTH__NONE != np->data.An.auth || np->child)
                return(1);
-       return(mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_NOARGS));
+       return(mdoc_nmsg(mdoc, np, MANDOCERR_NOARGS));
 }
 
 
@@ -1042,7 +1110,8 @@ post_it(POST_ARGS)
                return(1);
 
        n = mdoc->last->parent->parent;
-       lt = n->data.Bl.type;
+       assert(n->data.Bl);
+       lt = n->data.Bl->type;
 
        if (LIST__NONE == lt) {
                mdoc_nmsg(mdoc, mdoc->last, MANDOCERR_LISTTYPE);
@@ -1085,14 +1154,8 @@ post_it(POST_ARGS)
                                return(0);
                break;
        case (LIST_column):
-               cols = -1;
-               for (i = 0; i < (int)n->args->argc; i++)
-                       if (MDOC_Column == n->args->argv[i].arg) {
-                               cols = (int)n->args->argv[i].sz;
-                               break;
-                       }
+               cols = (int)n->data.Bl->ncols;
 
-               assert(-1 != cols);
                assert(NULL == mdoc->last->head->child);
 
                if (NULL == mdoc->last->body->child)
@@ -1131,13 +1194,8 @@ post_bl_head(POST_ARGS)
        assert(mdoc->last->parent);
        n = mdoc->last->parent;
 
-       if (LIST_column == n->data.Bl.type) {
-               for (i = 0; i < (int)n->args->argc; i++)
-                       if (MDOC_Column == n->args->argv[i].arg)
-                               break;
-               assert(i < (int)n->args->argc);
-
-               if (n->args->argv[i].sz && mdoc->last->nchild) {
+       if (LIST_column == n->data.Bl->type) {
+               if (n->data.Bl->ncols && mdoc->last->nchild) {
                        mdoc_nmsg(mdoc, n, MANDOCERR_COLUMNS);
                        return(0);
                }
diff --git a/usr.bin/mandoc/regs.h b/usr.bin/mandoc/regs.h
deleted file mode 100644 (file)
index b06f981..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*     $Id: regs.h,v 1.2 2010/07/03 15:59:05 schwarze Exp $ */
-/*
- * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-#ifndef REGS_H
-#define REGS_H
-
-__BEGIN_DECLS
-
-enum   regs {
-       REG_nS = 0,     /* nS */
-       REG__MAX
-};
-
-struct reg {
-       int              set; /* whether set or not */
-       union {
-               unsigned u; /* unsigned integer */
-       } v;
-};
-
-/*
- * Registers are non-scoped state.  These can be manipulated directly in
- * libroff or indirectly in libman or libmdoc by macros.  These should
- * be implemented sparingly (we are NOT roffdoc!) and documented fully
- * in roff.7.
- */
-struct regset {
-       struct reg       regs[REG__MAX];
-};
-
-char            *roff_setstr(const char *, const char *);
-char            *roff_getstr(const char *);
-char            *roff_getstrn(const char *, size_t);
-void             roff_freestr(void);
-
-__END_DECLS
-
-#endif /*!REGS_H*/
index 85e558f..b9d1fd4 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: roff.3,v 1.3 2010/07/03 15:59:05 schwarze Exp $
+.\"    $Id: roff.3,v 1.4 2010/07/13 01:09:13 schwarze Exp $
 .\"
 .\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\"
@@ -14,7 +14,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 3 2010 $
+.Dd $Mdocdate: July 13 2010 $
 .Dt ROFF 3
 .Os
 .Sh NAME
@@ -27,7 +27,6 @@
 .Nd roff macro compiler library
 .Sh SYNOPSIS
 .In mandoc.h
-.In regs.h
 .In roff.h
 .Ft "struct roff *"
 .Fo roff_alloc
 .Fc
 .Ft void
 .Fn roff_reset "struct roff *roff"
-.In regs.h
-.Ft "char *"
-.Fn roff_setstr "const char *name" "const char *string"
-.Ft "char *"
-.Fn roff_getstr "const char *name"
-.Ft "char *"
-.Fn roff_getstrn "const char *name" "size_t len"
-.Ft void
-.Fn roff_freestr void
 .Sh DESCRIPTION
 The
 .Nm
@@ -154,52 +144,6 @@ Returns 0 on failure, 1 on success.
 Signals that the parse is complete.
 Returns 0 on failure, 1 on success.
 .El
-.Sh USER-DEFINED STRINGS
-Strings defined by the
-.Xr roff 7
-.Sx \&ds
-instruction are saved using the
-.Fn roff_setstr
-function and retrieved using the
-.Fn roff_getstr
-and
-.Fn roff_getstrn
-functions.
-.Pp
-These functions take the name of the string to be accessed
-as their first argument.
-While
-.Fn roff_getstr
-requires the name to be null-terminated,
-.Fn roff_getstrn
-accepts non-terminated strings, but requires the length of the name
-to be specified.
-.Pp
-The second argument to
-.Fn roff_setstr
-is the new value of the string.
-It will be copied to internal storage, so both pointers to constant
-strings and pointers to volatile storage are acceptable.
-.Pp
-All of these functions return a pointer to the new value of the string
-in internal storage, which should be considered read-only, so use
-.Xr strdup 3
-on it as appropriate.
-The read functions return NULL when a string of the specified name
-is not available or empty, and
-.Fn roff_setstr
-returns NULL when memory allocation fails.
-In the latter case, the string will remain unset.
-.Pp
-The function
-.Fn roff_freestr
-clears all user-defined strings.
-It always succeeds.
-Both
-.Fn roff_reset
-and
-.Fn roff_free
-call it.
 .Sh EXAMPLES
 See
 .Pa main.c
index 3ac36e1..d7bff4d 100644 (file)
@@ -1,6 +1,7 @@
-.\"    $Id: roff.7,v 1.6 2010/06/27 21:54:42 schwarze Exp $
+.\"    $Id: roff.7,v 1.7 2010/07/13 01:09:13 schwarze Exp $
 .\"
 .\" Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+.\" Copyright (c) 2010 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
@@ -14,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: June 27 2010 $
+.Dd $Mdocdate: July 13 2010 $
 .Dt ROFF 7
 .Os
 .Sh NAME
@@ -91,11 +92,20 @@ The syntax of this macro is the same as that of
 except that a leading argument must be specified.
 It is ignored, as are its children.
 .Ss \&ds
-Define a string.
-This macro is intended to have two arguments,
-the name of the string to define and its content.
-Currently, it is ignored including its arguments,
-and the number of arguments is not checked.
+Define a reserved word.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&ds No Cm key val
+.Pp
+The
+.Cm key
+and
+.Cm val
+strings are space-separated.
+The
+.Cm key
+values may be invoked in subsequent text by using \e*(NN for two-letter
+pairs, \e*N for one-letter, and \e*[NNN] for arbitrary-length values.
 .Ss \&de1
 The syntax of this macro is the same as that of
 .Sx \&ig ,
index 32cd742..4522f78 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: roff.c,v 1.7 2010/07/03 15:59:05 schwarze Exp $ */
+/*     $Id: roff.c,v 1.8 2010/07/13 01:09:13 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 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
@@ -27,8 +28,8 @@
 #include <stdio.h>
 
 #include "mandoc.h"
-#include "regs.h"
 #include "roff.h"
+#include "libmandoc.h"
 
 #define        RSTACK_MAX      128
 
@@ -60,6 +61,13 @@ enum roffrule {
        ROFFRULE_DENY
 };
 
+
+struct roffstr {
+       char            *name; /* key of symbol */
+       char            *string; /* current value */
+       struct roffstr  *next; /* next in list */
+};
+
 struct roff {
        struct roffnode *last; /* leaf of stack */
        mandocmsg        msg; /* err/warn/fatal messages */
@@ -67,6 +75,7 @@ struct        roff {
        enum roffrule    rstack[RSTACK_MAX]; /* stack of !`ie' rules */
        int              rstackpos; /* position in rstack */
        struct regset   *regs; /* read/writable registers */
+       struct roffstr  *first_string;
 };
 
 struct roffnode {
@@ -100,12 +109,6 @@ struct     roffmac {
        struct roffmac  *next;
 };
 
-struct roffstr {
-       char            *name;
-       char            *string;
-       struct roffstr  *next;
-} *first_string;
-
 static enum rofferr     roff_block(ROFF_ARGS);
 static enum rofferr     roff_block_text(ROFF_ARGS);
 static enum rofferr     roff_block_sub(ROFF_ARGS);
@@ -115,9 +118,16 @@ static     enum rofferr     roff_cond(ROFF_ARGS);
 static enum rofferr     roff_cond_text(ROFF_ARGS);
 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_freestr(struct roff *);
+static const char      *roff_getstrn(const struct roff *, 
+                               const char *, size_t);
 static enum rofferr     roff_line(ROFF_ARGS);
 static enum rofferr     roff_nr(ROFF_ARGS);
-static enum roffrule    roff_evalcond(const char *, int *);
+static int              roff_res(struct roff *, int, 
+                               char **, size_t *, int, int *);
+static void             roff_setstr(struct roff *,
+                               const char *, const char *);
 
 /* See roff_hash_find() */
 
@@ -267,7 +277,7 @@ roff_free1(struct roff *r)
 
        while (r->last)
                roffnode_pop(r);
-       roff_freestr();
+       roff_freestr(r);
 }
 
 
@@ -308,6 +318,72 @@ roff_alloc(struct regset *regs, const mandocmsg msg, void *data)
 }
 
 
+/*
+ * 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. 
+ */
+static int
+roff_res(struct roff *r, int ln, char **bufp,
+               size_t *szp, int pos, int *offs)
+{
+       const char      *cp, *cpp, *st, *res;
+       int              i, maxl;
+       size_t           nsz;
+       char            *n;
+
+       for (cp = &(*bufp)[pos]; (cpp = strstr(cp, "\\*")); cp++) {
+               cp = cpp + 2;
+               switch (*cp) {
+               case ('('):
+                       cp++;
+                       maxl = 2;
+                       break;
+               case ('['):
+                       cp++;
+                       maxl = 0;
+                       break;
+               default:
+                       maxl = 1;
+                       break;
+               }
+
+               st = cp;
+
+               for (i = 0; 0 == maxl || i < maxl; i++, cp++) {
+                       if ('\0' == *cp)
+                               return(1); /* Error. */
+                       if (0 == maxl && ']' == *cp)
+                               break;
+               }
+
+               res = roff_getstrn(r, st, (size_t)i);
+
+               if (NULL == res) {
+                       cp -= maxl ? 1 : 0;
+                       continue;
+               }
+
+               nsz = *szp + strlen(res) + 1;
+               n = mandoc_malloc(nsz);
+
+               *n = '\0';
+
+               strlcat(n, *bufp, (size_t)(cpp - *bufp + 1));
+               strlcat(n, res, nsz);
+               strlcat(n, cp + (maxl ? 0 : 1), nsz);
+
+               free(*bufp);
+
+               *bufp = n;
+               *szp = nsz;
+               return(0);
+       }
+
+       return(1);
+}
+
+
 enum rofferr
 roff_parseln(struct roff *r, int ln, char **bufp, 
                size_t *szp, int pos, int *offs)
@@ -315,6 +391,14 @@ roff_parseln(struct roff *r, int ln, char **bufp,
        enum rofft       t;
        int              ppos;
 
+       /*
+        * Run the reserved-word filter only if we have some reserved
+        * words to fill in.
+        */
+
+       if (r->first_string && ! roff_res(r, ln, bufp, szp, pos, offs))
+               return(ROFF_RERUN);
+
        /*
         * First, if a scope is open and we're not a macro, pass the
         * text through the macro's filter.  If a scope isn't open and
@@ -325,7 +409,8 @@ roff_parseln(struct roff *r, int ln, char **bufp,
                t = r->last->tok;
                assert(roffs[t].text);
                return((*roffs[t].text)
-                               (r, t, bufp, szp, ln, pos, pos, offs));
+                               (r, t, bufp, szp, 
+                                ln, pos, pos, offs));
        } else if ( ! ROFF_CTL((*bufp)[pos]))
                return(ROFF_CONT);
 
@@ -338,7 +423,8 @@ roff_parseln(struct roff *r, int ln, char **bufp,
                t = r->last->tok;
                assert(roffs[t].sub);
                return((*roffs[t].sub)
-                               (r, t, bufp, szp, ln, pos, pos, offs));
+                               (r, t, bufp, szp, 
+                                ln, pos, pos, offs));
        }
 
        /*
@@ -353,7 +439,8 @@ roff_parseln(struct roff *r, int ln, char **bufp,
 
        assert(roffs[t].proc);
        return((*roffs[t].proc)
-                       (r, t, bufp, szp, ln, ppos, pos, offs));
+                       (r, t, bufp, szp, 
+                        ln, ppos, pos, offs));
 }
 
 
@@ -880,7 +967,7 @@ roff_ds(ROFF_ARGS)
                        *end = '\0';
        }
 
-       roff_setstr(name, string);
+       roff_setstr(r, name, string);
        return(ROFF_IGN);
 }
 
@@ -924,73 +1011,53 @@ roff_nr(ROFF_ARGS)
 }
 
 
-char *
-roff_setstr(const char *name, const char *string)
+static void
+roff_setstr(struct roff *r, const char *name, const char *string)
 {
        struct roffstr   *n;
        char             *namecopy;
 
-       n = first_string;
+       n = r->first_string;
        while (n && strcmp(name, n->name))
                n = n->next;
-       if (n) {
-               free(n->string);
-       } else {
-               if (NULL == (namecopy = strdup(name)))
-                       return(NULL);
-               if (NULL == (n = malloc(sizeof(struct roffstr)))) {
-                       free(n);
-                       return(NULL);
-               }
-               n->name = namecopy;
-               n->next = first_string;
-               first_string = n;
-       }
-       if (string)
-               n->string = strdup(string);
-       else
-               n->string = NULL;
-       return(n->string);
-}
 
-char *
-roff_getstr(const char *name)
-{
-       struct roffstr   *n;
+       if (NULL == n) {
+               namecopy = mandoc_strdup(name);
+               n = mandoc_malloc(sizeof(struct roffstr));
+               n->name = namecopy;
+               n->next = r->first_string;
+               r->first_string = n;
+       } else
+               free(n->string);
 
-       n = first_string;
-       while (n && strcmp(name, n->name))
-               n = n->next;
-       if (n)
-               return(n->string);
-       else
-               return(NULL);
+       n->string = string ? strdup(string) : NULL;
 }
 
-char *
-roff_getstrn(const char *name, size_t len)
+
+static const char *
+roff_getstrn(const struct roff *r, const char *name, size_t len)
 {
-       struct roffstr   *n;
+       const struct roffstr *n;
 
-       n = first_string;
+       n = r->first_string;
        while (n && (strncmp(name, n->name, len) || '\0' != n->name[len]))
                n = n->next;
-       if (n)
-               return(n->string);
-       else
-               return(NULL);
+
+       return(n ? n->string : NULL);
 }
 
-void
-roff_freestr(void)
+
+static void
+roff_freestr(struct roff *r)
 {
        struct roffstr   *n, *nn;
 
-       for (n = first_string; n; n = nn) {
+       for (n = r->first_string; n; n = nn) {
                free(n->name);
                free(n->string);
                nn = n->next;
                free(n);
        }
-       first_string = NULL;
+
+       r->first_string = NULL;
 }
index 45b6036..459c17a 100644 (file)
@@ -1,6 +1,7 @@
-/*     $Id: term.c,v 1.43 2010/07/03 15:59:05 schwarze Exp $ */
+/*     $Id: term.c,v 1.44 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 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
@@ -26,7 +27,6 @@
 #include "mandoc.h"
 #include "chars.h"
 #include "out.h"
-#include "regs.h"
 #include "term.h"
 #include "main.h"
 
@@ -374,11 +374,6 @@ res(struct termp *p, const char *word, size_t len)
        size_t           sz;
 
        rhs = chars_a2res(p->symtab, word, len, &sz);
-       if (NULL == rhs) {
-               rhs = roff_getstrn(word, len);
-               if (rhs)
-                       sz = strlen(rhs);
-       }
        if (rhs)
                encode(p, rhs, sz);
 }
@@ -655,6 +650,7 @@ term_strlen(const struct termp *p, const char *cp)
 }
 
 
+/* ARGSUSED */
 size_t
 term_vspan(const struct termp *p, const struct roffsu *su)
 {
@@ -694,39 +690,11 @@ term_vspan(const struct termp *p, const struct roffsu *su)
 size_t
 term_hspan(const struct termp *p, const struct roffsu *su)
 {
-       double           r;
-
-       /* XXX: CM, IN, and PT are approximations. */
-
-       switch (su->unit) {
-       case (SCALE_CM):
-               r = 4 * su->scale;
-               break;
-       case (SCALE_IN):
-               /* XXX: this is an approximation. */
-               r = 10 * su->scale;
-               break;
-       case (SCALE_PC):
-               r = (10 * su->scale) / 6;
-               break;
-       case (SCALE_PT):
-               r = (10 * su->scale) / 72;
-               break;
-       case (SCALE_MM):
-               r = su->scale / 1000; /* FIXME: double-check. */
-               break;
-       case (SCALE_VS):
-               r = su->scale * 2 - 1; /* FIXME: double-check. */
-               break;
-       default:
-               r = su->scale;
-               break;
-       }
+       double           v;
 
-       if (r < 0.0)
-               r = 0.0;
-       return((size_t)/* LINTED */
-                       r);
+       v = ((*p->hspan)(p, su));
+       if (v < 0.0)
+               v = 0.0;
+       return((size_t) /* LINTED */
+                       v);
 }
-
-
index 726915f..ff2585a 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: term.h,v 1.24 2010/06/29 14:41:28 schwarze Exp $ */
+/*     $Id: term.h,v 1.25 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -42,25 +42,27 @@ enum        termfont {
 typedef void   (*term_margin)(struct termp *, const void *);
 
 struct termp_ps {
-       int               psstate;      /* state of ps output */
+       int               flags;
 #define        PS_INLINE        (1 << 0)       /* we're in a word */
 #define        PS_MARGINS       (1 << 1)       /* we're in the margins */
-       size_t            pscol;        /* visible column (points) */
-       size_t            psrow;        /* visible row (points) */
+#define        PS_NEWPAGE       (1 << 2)       /* new page, no words yet */
+       size_t            pscol;        /* visible column (AFM units) */
+       size_t            psrow;        /* visible row (AFM units) */
        char             *psmarg;       /* margin buf */
        size_t            psmargsz;     /* margin buf size */
        size_t            psmargcur;    /* cur index in margin buf */
        char              last;         /* character buffer */
        enum termfont     lastf;        /* last set font */
+       size_t            scale;        /* font scaling factor */
        size_t            pages;        /* number of pages shown */
-       size_t            lineheight;   /* each line's height (points) */
-       size_t            top;          /* body top (points) */
-       size_t            bottom;       /* body bottom (points) */
-       size_t            height;       /* total height (points) */
-       size_t            width;        /* total width (points) */
-       size_t            left;         /* body left (points) */
-       size_t            header;       /* header position (points) */
-       size_t            footer;       /* footer position (points) */
+       size_t            lineheight;   /* line height (AFM units) */
+       size_t            top;          /* body top (AFM units) */
+       size_t            bottom;       /* body bottom (AFM units) */
+       size_t            height;       /* page height (AFM units */
+       size_t            width;        /* page width (AFM units) */
+       size_t            left;         /* body left (AFM units) */
+       size_t            header;       /* header pos (AFM units) */
+       size_t            footer;       /* footer pos (AFM units) */
 };
 
 struct termp {
@@ -103,6 +105,8 @@ struct      termp {
        void            (*endline)(struct termp *);
        void            (*advance)(struct termp *, size_t);
        size_t          (*width)(const struct termp *, char);
+       double          (*hspan)(const struct termp *,
+                               const struct roffsu *);
        const void       *argf;         /* arg for headf/footf */
        union {
                struct termp_ps ps;
index da20706..21b1abb 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: term_ascii.c,v 1.2 2010/06/26 19:08:00 schwarze Exp $ */
+/*     $Id: term_ascii.c,v 1.3 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include "term.h"
 #include "main.h"
 
-static void              ascii_endline(struct termp *);
-static void              ascii_letter(struct termp *, char);
-static void              ascii_begin(struct termp *);
+static double            ascii_hspan(const struct termp *,
+                               const struct roffsu *);
+static size_t            ascii_width(const struct termp *, char);
 static void              ascii_advance(struct termp *, size_t);
+static void              ascii_begin(struct termp *);
 static void              ascii_end(struct termp *);
-static size_t            ascii_width(const struct termp *, char);
+static void              ascii_endline(struct termp *);
+static void              ascii_letter(struct termp *, char);
 
 
 void *
@@ -51,12 +53,13 @@ ascii_alloc(char *outopts)
        p->tabwidth = 5;
        p->defrmargin = 78;
 
-       p->type = TERMTYPE_CHAR;
-       p->letter = ascii_letter;
+       p->advance = ascii_advance;
        p->begin = ascii_begin;
        p->end = ascii_end;
        p->endline = ascii_endline;
-       p->advance = ascii_advance;
+       p->hspan = ascii_hspan;
+       p->letter = ascii_letter;
+       p->type = TERMTYPE_CHAR;
        p->width = ascii_width;
 
        toks[0] = "width";
@@ -79,6 +82,7 @@ ascii_alloc(char *outopts)
 }
 
 
+/* ARGSUSED */
 static size_t
 ascii_width(const struct termp *p, char c)
 {
@@ -139,3 +143,43 @@ ascii_advance(struct termp *p, size_t len)
        for (i = 0; i < len; i++)
                putchar(' ');
 }
+
+
+/* ARGSUSED */
+static double
+ascii_hspan(const struct termp *p, const struct roffsu *su)
+{
+       double           r;
+
+       /*
+        * Approximate based on character width.  These are generated
+        * entirely by eyeballing the screen, but appear to be correct.
+        */
+
+       switch (su->unit) {
+       case (SCALE_CM):
+               r = 4 * su->scale;
+               break;
+       case (SCALE_IN):
+               r = 10 * su->scale;
+               break;
+       case (SCALE_PC):
+               r = (10 * su->scale) / 6;
+               break;
+       case (SCALE_PT):
+               r = (10 * su->scale) / 72;
+               break;
+       case (SCALE_MM):
+               r = su->scale / 1000;
+               break;
+       case (SCALE_VS):
+               r = su->scale * 2 - 1;
+               break;
+       default:
+               r = su->scale;
+               break;
+       }
+
+       return(r);
+}
+
index eb06b30..44fa34e 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: term_ps.c,v 1.5 2010/06/29 15:49:52 schwarze Exp $ */
+/*     $Id: term_ps.c,v 1.6 2010/07/13 01:09:13 schwarze Exp $ */
 /*
- * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
+ * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
+#include <unistd.h>
 
 #include "out.h"
 #include "main.h"
 #include "term.h"
 
+/* Convert PostScript point "x" to an AFM unit. */
+#define        PNT2AFM(p, x) /* LINTED */ \
+       (size_t)((double)(x) * (1000.0 / (double)(p)->engine.ps.scale))
+
+/* Convert an AFM unit "x" to a PostScript points */
+#define        AFM2PNT(p, x) /* LINTED */ \
+       (size_t)((double)(x) / (1000.0 / (double)(p)->engine.ps.scale))
+
 struct glyph {
-       int               wx; /* WX in AFM */
+       size_t            wx; /* WX in AFM */
 };
 
 struct font {
@@ -49,296 +58,296 @@ struct    font {
  */
 
 static const struct font fonts[TERMFONT__MAX] = {
-       { "Courier", {
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
+       { "Times-Roman", {
+               { 250 },
+               { 333 },
+               { 408 },
+               { 500 },
+               { 500 },
+               { 833 },
+               { 778 },
+               { 333 },
+               { 333 },
+               { 333 },
+               { 500 },
+               { 564 },
+               { 250 },
+               { 333 },
+               { 250 },
+               { 278 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 500 },
+               { 278 },
+               { 278 },
+               { 564 },
+               { 564 },
+               { 564 },
+               { 444 },
+               { 921 },
+               { 722 },
+               { 667 },
+               { 667 },
+               { 722 },
+               { 611 },
+               { 556 },
+               { 722 },
+               { 722 },
+               { 333 },
+               { 389 },
+               { 722 },
+               { 611 },
+               { 889 },
+               { 722 },
+               { 722 },
+               { 556 },
+               { 722 },
+               { 667 },
+               { 556 },
+               { 611 },
+               { 722 },
+               { 722 },
+               { 944 },
+               { 722 },
+               { 722 },
+               { 611 },
+               { 333 },
+               { 278 },
+               { 333 },
+               { 469 },
+               { 500 },
+               { 333 },
+               { 444 },
+               { 500 },
+               { 444 },
+               {  500},
+               {  444},
+               {  333},
+               {  500},
+               {  500},
+               {  278},
+               {  278},
+               {  500},
+               {  278},
+               {  778},
+               {  500},
+               {  500},
+               {  500},
+               {  500},
+               {  333},
+               {  389},
+               {  278},
+               {  500},
+               {  500},
+               {  722},
+               {  500},
+               {  500},
+               {  444},
+               {  480},
+               {  200},
+               {  480},
+               {  541},
        } },
-       { "Courier-Bold", {
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
+       { "Times-Bold", {
+               { 250  },
+               { 333  },
+               { 555  },
+               { 500  },
+               { 500  },
+               { 1000 },
+               { 833  },
+               { 333  },
+               { 333  },
+               { 333  },
+               { 500  },
+               { 570  },
+               { 250  },
+               { 333  },
+               { 250  },
+               { 278  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 333  },
+               { 333  },
+               { 570  },
+               { 570  },
+               { 570  },
+               { 500  },
+               { 930  },
+               { 722  },
+               { 667  },
+               { 722  },
+               { 722  },
+               { 667  },
+               { 611  },
+               { 778  },
+               { 778  },
+               { 389  },
+               { 500  },
+               { 778  },
+               { 667  },
+               { 944  },
+               { 722  },
+               { 778  },
+               { 611  },
+               { 778  },
+               { 722  },
+               { 556  },
+               { 667  },
+               { 722  },
+               { 722  },
+               { 1000 },
+               { 722  },
+               { 722  },
+               { 667  },
+               { 333  },
+               { 278  },
+               { 333  },
+               { 581  },
+               { 500  },
+               { 333  },
+               { 500  },
+               { 556  },
+               { 444  },
+               {  556 },
+               {  444 },
+               {  333 },
+               {  500 },
+               {  556 },
+               {  278 },
+               {  333 },
+               {  556 },
+               {  278 },
+               {  833 },
+               {  556 },
+               {  500 },
+               {  556 },
+               {  556 },
+               {  444 },
+               {  389 },
+               {  333 },
+               {  556 },
+               {  500 },
+               {  722 },
+               {  500 },
+               {  500 },
+               {  444 },
+               {  394 },
+               {  220 },
+               {  394 },
+               {  520 },
        } },
-       { "Courier-Oblique", {
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
-               { 600 },
+       { "Times-Italic", {
+               { 250  },
+               { 333  },
+               { 420  },
+               { 500  },
+               { 500  },
+               { 833  },
+               { 778  },
+               { 333  },
+               { 333  },
+               { 333  },
+               { 500  },
+               { 675  },
+               { 250  },
+               { 333  },
+               { 250  },
+               { 278  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 500  },
+               { 333  },
+               { 333  },
+               { 675  },
+               { 675  },
+               { 675  },
+               { 500  },
+               { 920  },
+               { 611  },
+               { 611  },
+               { 667  },
+               { 722  },
+               { 611  },
+               { 611  },
+               { 722  },
+               { 722  },
+               { 333  },
+               { 444  },
+               { 667  },
+               { 556  },
+               { 833  },
+               { 667  },
+               { 722  },
+               { 611  },
+               { 722  },
+               { 611  },
+               { 500  },
+               { 556  },
+               { 722  },
+               { 611  },
+               { 833  },
+               { 611  },
+               { 556  },
+               { 556  },
+               { 389  },
+               { 278  },
+               { 389  },
+               { 422  },
+               { 500  },
+               { 333  },
+               { 500  },
+               { 500  },
+               { 444  },
+               {  500 },
+               {  444 },
+               {  278 },
+               {  500 },
+               {  500 },
+               {  278 },
+               {  278 },
+               {  444 },
+               {  278 },
+               {  722 },
+               {  500 },
+               {  500 },
+               {  500 },
+               {  500 },
+               {  389 },
+               {  389 },
+               {  278 },
+               {  500 },
+               {  444 },
+               {  667 },
+               {  444 },
+               {  444 },
+               {  389 },
+               {  400 },
+               {  275 },
+               {  400 },
+               {  541 },
        } },
 };
 
@@ -359,13 +368,15 @@ static    const struct font fonts[TERMFONT__MAX] = {
        } while (/* CONSTCOND */ 0)
 
 
-static void              ps_letter(struct termp *, char);
+static double            ps_hspan(const struct termp *,
+                               const struct roffsu *);
+static size_t            ps_width(const struct termp *, char);
+static void              ps_advance(struct termp *, size_t);
 static void              ps_begin(struct termp *);
 static void              ps_end(struct termp *);
-static void              ps_advance(struct termp *, size_t);
 static void              ps_endline(struct termp *);
 static void              ps_fclose(struct termp *);
-static size_t            ps_width(const struct termp *, char);
+static void              ps_letter(struct termp *, char);
 static void              ps_pclose(struct termp *);
 static void              ps_pletter(struct termp *, int);
 static void              ps_printf(struct termp *, const char *, ...);
@@ -377,57 +388,100 @@ void *
 ps_alloc(char *outopts)
 {
        struct termp    *p;
-       size_t           pagex, pagey, margin;
+       size_t           pagex, pagey, marginx, marginy, lineheight;
        const char      *toks[2];
+       const char      *pp;
        char            *v;
 
        if (NULL == (p = term_alloc(TERMENC_ASCII)))
                return(NULL);
 
-       /* Default is USA letter. */
-       pagex = 612;
-       pagey = 792;
-       margin = 72;
-
-       p->type = TERMTYPE_PS;
-       p->letter = ps_letter;
+       p->advance = ps_advance;
        p->begin = ps_begin;
        p->end = ps_end;
-       p->advance = ps_advance;
        p->endline = ps_endline;
+       p->hspan = ps_hspan;
+       p->letter = ps_letter;
+       p->type = TERMTYPE_PS;
        p->width = ps_width;
-
+       
        toks[0] = "paper";
        toks[1] = NULL;
 
+       pp = NULL;
+
        while (outopts && *outopts)
                switch (getsubopt(&outopts, UNCONST(toks), &v)) {
                case (0):
-                       if (0 == strcasecmp(v, "a4")) {
-                               pagex = 595;
-                               pagey = 842;
-                       } else if (0 == strcasecmp(v, "letter")) {
-                               pagex = 612;
-                               pagey = 792;
-                       }
+                       pp = v;
                        break;
                default:
                        break;
                }
 
-       assert(margin * 2 < pagex);
-       assert(margin * 2 < pagey);
+       /* Default to US letter (millimetres). */
+
+       pagex = 216;
+       pagey = 279;
+
+       /*
+        * The ISO-269 paper sizes can be calculated automatically, but
+        * it would require bringing in -lm for pow() and I'd rather not
+        * do that.  So just do it the easy way for now.  Since this
+        * only happens once, I'm not terribly concerned.
+        */
+
+       if (pp && strcasecmp(pp, "letter")) {
+               if (0 == strcasecmp(pp, "a3")) {
+                       pagex = 297;
+                       pagey = 420;
+               } else if (0 == strcasecmp(pp, "a4")) {
+                       pagex = 210;
+                       pagey = 297;
+               } else if (0 == strcasecmp(pp, "a5")) {
+                       pagex = 148;
+                       pagey = 210;
+               } else if (0 == strcasecmp(pp, "legal")) {
+                       pagex = 216;
+                       pagey = 356;
+               } else if (2 != sscanf(pp, "%zux%zu", &pagex, &pagey))
+                       fprintf(stderr, "%s: Unknown paper\n", pp);
+       } else if (NULL == pp)
+               pp = "letter";
+
+       /* 
+        * This MUST be defined before any PNT2AFM or AFM2PNT
+        * calculations occur.
+        */
+
+       p->engine.ps.scale = 11;
+
+       /* Remember millimetres -> AFM units. */
+
+       pagex = PNT2AFM(p, ((double)pagex * 2.834));
+       pagey = PNT2AFM(p, ((double)pagey * 2.834));
+
+       /* Margins are 1/9 the page x and y. */
+
+       marginx = /* LINTED */
+               (size_t)((double)pagex / 9.0);
+       marginy = /* LINTED */
+               (size_t)((double)pagey / 9.0);
+
+       /* Line-height is 1.4em. */
+
+       lineheight = PNT2AFM(p, ((double)p->engine.ps.scale * 1.4));
 
        p->engine.ps.width = pagex;
        p->engine.ps.height = pagey;
-       p->engine.ps.header = pagey - (margin / 2);
-       p->engine.ps.top = pagey - margin;
-       p->engine.ps.footer = (margin / 2);
-       p->engine.ps.bottom = margin;
-       p->engine.ps.left = margin;
-       p->engine.ps.lineheight = 12;
-
-       p->defrmargin = pagex - (margin * 2);
+       p->engine.ps.header = pagey - (marginy / 2) - (lineheight / 2);
+       p->engine.ps.top = pagey - marginy;
+       p->engine.ps.footer = (marginy / 2) - (lineheight / 2);
+       p->engine.ps.bottom = marginy;
+       p->engine.ps.left = marginx;
+       p->engine.ps.lineheight = lineheight;
+
+       p->defrmargin = pagex - (marginx * 2);
        return(p);
 }
 
@@ -460,7 +514,7 @@ ps_printf(struct termp *p, const char *fmt, ...)
         * into our growable margin buffer.
         */
 
-       if ( ! (PS_MARGINS & p->engine.ps.psstate)) {
+       if ( ! (PS_MARGINS & p->engine.ps.flags)) {
                vprintf(fmt, ap);
                va_end(ap);
                return;
@@ -489,7 +543,7 @@ ps_putchar(struct termp *p, char c)
 
        /* See ps_printf(). */
 
-       if ( ! (PS_MARGINS & p->engine.ps.psstate)) {
+       if ( ! (PS_MARGINS & p->engine.ps.flags)) {
                putchar(c);
                return;
        }
@@ -513,12 +567,14 @@ ps_end(struct termp *p)
         * well as just one.
         */
 
-       assert(0 == p->engine.ps.psstate);
-       assert('\0' == p->engine.ps.last);
-       assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
-       printf("%s", p->engine.ps.psmarg);
-       p->engine.ps.pages++;
-       printf("showpage\n");
+       if ( ! (PS_NEWPAGE & p->engine.ps.flags)) {
+               assert(0 == p->engine.ps.flags);
+               assert('\0' == p->engine.ps.last);
+               assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
+               printf("%s", p->engine.ps.psmarg);
+               p->engine.ps.pages++;
+               printf("showpage\n");
+       }
 
        printf("%%%%Trailer\n");
        printf("%%%%Pages: %zu\n", p->engine.ps.pages);
@@ -543,7 +599,7 @@ ps_begin(struct termp *p)
        }
 
        p->engine.ps.psmargcur = 0;
-       p->engine.ps.psstate = PS_MARGINS;
+       p->engine.ps.flags = PS_MARGINS;
        p->engine.ps.pscol = p->engine.ps.left;
        p->engine.ps.psrow = p->engine.ps.header;
 
@@ -558,9 +614,9 @@ ps_begin(struct termp *p)
        (*p->footf)(p, p->argf);
        (*p->endline)(p);
 
-       p->engine.ps.psstate &= ~PS_MARGINS;
+       p->engine.ps.flags &= ~PS_MARGINS;
 
-       assert(0 == p->engine.ps.psstate);
+       assert(0 == p->engine.ps.flags);
        assert(p->engine.ps.psmarg);
        assert('\0' != p->engine.ps.psmarg[0]);
 
@@ -578,22 +634,18 @@ ps_begin(struct termp *p)
        printf("%%%%Orientation: Portrait\n");
        printf("%%%%Pages: (atend)\n");
        printf("%%%%PageOrder: Ascend\n");
-       printf("%%%%Orientation: Portrait\n");
        printf("%%%%DocumentMedia: Default %zu %zu 0 () ()\n",
-                       p->engine.ps.width,
-                       p->engine.ps.height);
+                       AFM2PNT(p, p->engine.ps.width),
+                       AFM2PNT(p, p->engine.ps.height));
        printf("%%%%DocumentNeededResources: font");
        for (i = 0; i < (int)TERMFONT__MAX; i++)
                printf(" %s", fonts[i].name);
        printf("\n%%%%EndComments\n");
 
-       printf("%%%%Page: %zu %zu\n", 
-                       p->engine.ps.pages + 1, 
-                       p->engine.ps.pages + 1);
-
-       ps_setfont(p, TERMFONT_NONE);
        p->engine.ps.pscol = p->engine.ps.left;
        p->engine.ps.psrow = p->engine.ps.top;
+       p->engine.ps.flags |= PS_NEWPAGE;
+       ps_setfont(p, TERMFONT_NONE);
 }
 
 
@@ -601,19 +653,36 @@ static void
 ps_pletter(struct termp *p, int c)
 {
        int              f;
+
+       /*
+        * If we haven't opened a page context, then output that we're
+        * in a new page and make sure the font is correctly set.
+        */
+
+       if (PS_NEWPAGE & p->engine.ps.flags) {
+               printf("%%%%Page: %zu %zu\n", 
+                               p->engine.ps.pages + 1, 
+                               p->engine.ps.pages + 1);
+               ps_printf(p, "/%s %zu selectfont\n", 
+                               fonts[(int)p->engine.ps.lastf].name, 
+                               p->engine.ps.scale);
+               p->engine.ps.flags &= ~PS_NEWPAGE;
+       }
        
        /*
         * If we're not in a PostScript "word" context, then open one
         * now at the current cursor.
         */
 
-       if ( ! (PS_INLINE & p->engine.ps.psstate)) {
+       if ( ! (PS_INLINE & p->engine.ps.flags)) {
                ps_printf(p, "%zu %zu moveto\n(", 
-                               p->engine.ps.pscol, 
-                               p->engine.ps.psrow);
-               p->engine.ps.psstate |= PS_INLINE;
+                               AFM2PNT(p, p->engine.ps.pscol),
+                               AFM2PNT(p, p->engine.ps.psrow));
+               p->engine.ps.flags |= PS_INLINE;
        }
 
+       assert( ! (PS_NEWPAGE & p->engine.ps.flags));
+
        /*
         * We need to escape these characters as per the PostScript
         * specification.  We would also escape non-graphable characters
@@ -639,13 +708,13 @@ ps_pletter(struct termp *p, int c)
 
        if (c <= 32 || (c - 32 > MAXCHAR)) {
                ps_putchar(p, ' ');
-               p->engine.ps.pscol += (fonts[f].gly[0].wx / 100);
+               p->engine.ps.pscol += fonts[f].gly[0].wx;
                return;
        } 
 
-       ps_putchar(p, c);
+       ps_putchar(p, (char)c);
        c -= 32;
-       p->engine.ps.pscol += (fonts[f].gly[c].wx / 100);
+       p->engine.ps.pscol += fonts[f].gly[c].wx;
 }
 
 
@@ -659,11 +728,11 @@ ps_pclose(struct termp *p)
         * or anything).
         */
 
-       if ( ! (PS_INLINE & p->engine.ps.psstate))
+       if ( ! (PS_INLINE & p->engine.ps.flags))
                return;
        
        ps_printf(p, ") show\n");
-       p->engine.ps.psstate &= ~PS_INLINE;
+       p->engine.ps.flags &= ~PS_INLINE;
 }
 
 
@@ -688,7 +757,7 @@ ps_fclose(struct termp *p)
                p->engine.ps.last = '\0';
        }
 
-       if ( ! (PS_INLINE & p->engine.ps.psstate))
+       if ( ! (PS_INLINE & p->engine.ps.flags))
                return;
 
        ps_pclose(p);
@@ -773,7 +842,16 @@ ps_endline(struct termp *p)
         * lines, we'll do nasty stuff. 
         */
 
-       if (PS_MARGINS & p->engine.ps.psstate)
+       if (PS_MARGINS & p->engine.ps.flags)
+               return;
+
+       /* Left-justify. */
+
+       p->engine.ps.pscol = p->engine.ps.left;
+
+       /* If we haven't printed anything, return. */
+
+       if (PS_NEWPAGE & p->engine.ps.flags)
                return;
 
        /*
@@ -781,7 +859,6 @@ ps_endline(struct termp *p)
         * showpage and restart our row.
         */
 
-       p->engine.ps.pscol = p->engine.ps.left;
        if (p->engine.ps.psrow >= p->engine.ps.lineheight + 
                        p->engine.ps.bottom) {
                p->engine.ps.psrow -= p->engine.ps.lineheight;
@@ -790,12 +867,11 @@ ps_endline(struct termp *p)
 
        assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
        printf("%s", p->engine.ps.psmarg);
-       printf("%%%%Page: %zu %zu\n", 
-                       p->engine.ps.pages + 1, 
-                       p->engine.ps.pages + 1);
        printf("showpage\n");
        p->engine.ps.pages++;
        p->engine.ps.psrow = p->engine.ps.top;
+       assert( ! (PS_NEWPAGE & p->engine.ps.flags));
+       p->engine.ps.flags |= PS_NEWPAGE;
 }
 
 
@@ -804,8 +880,18 @@ ps_setfont(struct termp *p, enum termfont f)
 {
 
        assert(f < TERMFONT__MAX);
-       ps_printf(p, "/%s 10 selectfont\n", fonts[(int)f].name);
        p->engine.ps.lastf = f;
+       
+       /*
+        * If we're still at the top of the page, let the font-setting
+        * be delayed until we actually have stuff to print.
+        */
+
+       if (PS_NEWPAGE & p->engine.ps.flags)
+               return;
+
+       ps_printf(p, "/%s %zu selectfont\n", 
+                       fonts[(int)f].name, p->engine.ps.scale);
 }
 
 
@@ -815,8 +901,55 @@ ps_width(const struct termp *p, char c)
 {
 
        if (c <= 32 || c - 32 >= MAXCHAR)
-               return(fonts[(int)TERMFONT_NONE].gly[0].wx / 100);
+               return(fonts[(int)TERMFONT_NONE].gly[0].wx);
 
        c -= 32;
-       return(fonts[(int)TERMFONT_NONE].gly[(int)c].wx / 100);
+       return(fonts[(int)TERMFONT_NONE].gly[(int)c].wx);
 }
+
+
+static double
+ps_hspan(const struct termp *p, const struct roffsu *su)
+{
+       double           r;
+       
+       /*
+        * All of these measurements are derived by converting from the
+        * native measurement to AFM units.
+        */
+
+       switch (su->unit) {
+       case (SCALE_CM):
+               r = PNT2AFM(p, su->scale * 28.34);
+               break;
+       case (SCALE_IN):
+               r = PNT2AFM(p, su->scale * 72);
+               break;
+       case (SCALE_PC):
+               r = PNT2AFM(p, su->scale * 12);
+               break;
+       case (SCALE_PT):
+               r = PNT2AFM(p, su->scale * 100);
+               break;
+       case (SCALE_EM):
+               r = su->scale * 
+                       fonts[(int)TERMFONT_NONE].gly[109 - 32].wx;
+               break;
+       case (SCALE_MM):
+               r = PNT2AFM(p, su->scale * 2.834);
+               break;
+       case (SCALE_EN):
+               r = su->scale * 
+                       fonts[(int)TERMFONT_NONE].gly[110 - 32].wx;
+               break;
+       case (SCALE_VS):
+               r = su->scale * p->engine.ps.lineheight;
+               break;
+       default:
+               r = su->scale;
+               break;
+       }
+
+       return(r);
+}
+
index 82c7e09..b775ca1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: tree.c,v 1.9 2010/06/29 17:10:30 schwarze Exp $ */
+/*     $Id: tree.c,v 1.10 2010/07/13 01:09:13 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -20,7 +20,6 @@
 #include <time.h>
 
 #include "mandoc.h"
-#include "regs.h"
 #include "mdoc.h"
 #include "man.h"
 #include "main.h"