Sync to bsd.lv; in particular, pull in lots of bug fixes.
authorschwarze <schwarze@openbsd.org>
Sun, 25 Jul 2010 18:05:54 +0000 (18:05 +0000)
committerschwarze <schwarze@openbsd.org>
Sun, 25 Jul 2010 18:05:54 +0000 (18:05 +0000)
new features:
* support the .in macro in man(7)
* support minimal PDF output
* support .Sm in mdoc(7) HTML output
* support .Vb and .nf in man(7) HTML output
* complete the mdoc(7) manual
bug fixes:
* do not let mdoc(7) .Pp produce a newline before/after .Sh; reported by jmc@
* avoid double blank lines related to man(7) .sp and .br
* let man(7) .nf and .fi flush the line; reported by jsg@ and naddy@
* let "\ " produce a non-breaking space; reported by deraadt@
* discard \m colour escape sequences; reported by J.C. Roberts
* map undefined 1-character-escapes to the literal character itself
maintenance:
* express mdoc(7) arguments in terms of an enum for additional type-safety
* simplify mandoc_special() and a2roffdeco()
* use strcspn in term_word() in place of a manual loop
* minor optimisations in the -Tps and -Thtml formatting frontends

29 files changed:
usr.bin/mandoc/chars.c
usr.bin/mandoc/chars.h
usr.bin/mandoc/chars.in
usr.bin/mandoc/html.c
usr.bin/mandoc/html.h
usr.bin/mandoc/main.c
usr.bin/mandoc/main.h
usr.bin/mandoc/man.c
usr.bin/mandoc/man.h
usr.bin/mandoc/man_action.c
usr.bin/mandoc/man_html.c
usr.bin/mandoc/man_macro.c
usr.bin/mandoc/man_term.c
usr.bin/mandoc/man_validate.c
usr.bin/mandoc/mandoc.1
usr.bin/mandoc/mandoc.c
usr.bin/mandoc/mandoc.h
usr.bin/mandoc/mdoc.7
usr.bin/mandoc/mdoc.h
usr.bin/mandoc/mdoc_argv.c
usr.bin/mandoc/mdoc_html.c
usr.bin/mandoc/mdoc_term.c
usr.bin/mandoc/mdoc_validate.c
usr.bin/mandoc/out.c
usr.bin/mandoc/out.h
usr.bin/mandoc/roff.c
usr.bin/mandoc/term.c
usr.bin/mandoc/term.h
usr.bin/mandoc/term_ps.c

index fb3c0b6..ed1f8b0 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: chars.c,v 1.8 2010/06/06 20:30:08 schwarze Exp $ */
+/*     $Id: chars.c,v 1.9 2010/07/25 18:05:54 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * 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
@@ -29,10 +29,8 @@ struct       ln {
        struct ln        *next;
        const char       *code;
        const char       *ascii;
-       const char       *html;
-       size_t            codesz;
        size_t            asciisz;
-       size_t            htmlsz;
+       int               unicode;
        int               type;
 #define        CHARS_CHAR       (1 << 0)
 #define        CHARS_STRING     (1 << 1)
@@ -41,12 +39,12 @@ struct      ln {
 
 #define        LINES_MAX         370
 
-#define CHAR(w, x, y, z, a, b) \
-       { NULL, (w), (y), (a), (x), (z), (b), CHARS_CHAR },
-#define STRING(w, x, y, z, a, b) \
-       { NULL, (w), (y), (a), (x), (z), (b), CHARS_STRING },
-#define BOTH(w, x, y, z, a, b) \
-       { NULL, (w), (y), (a), (x), (z), (b), CHARS_BOTH },
+#define CHAR(in, ch, chsz, code) \
+       { NULL, (in), (ch), (chsz), (code), CHARS_CHAR },
+#define STRING(in, ch, chsz, code) \
+       { NULL, (in), (ch), (chsz), (code), CHARS_STRING },
+#define BOTH(in, ch, chsz, code) \
+       { NULL, (in), (ch), (chsz), (code), CHARS_BOTH },
 
 #define        CHAR_TBL_START    static struct ln lines[LINES_MAX] = {
 #define        CHAR_TBL_END      };
@@ -60,8 +58,7 @@ struct        tbl {
 
 static inline int        match(const struct ln *,
                                const char *, size_t, int);
-static const char       *find(struct tbl *, const char *, 
-                               size_t, size_t *, int);
+static const struct ln  *find(struct tbl *, const char *, size_t, int);
 
 
 void
@@ -122,31 +119,80 @@ chars_init(enum chars type)
 }
 
 
+/* 
+ * Special character to Unicode codepoint.
+ */
+int
+chars_spec2cp(void *arg, const char *p, size_t sz)
+{
+       const struct ln *ln;
+
+       ln = find((struct tbl *)arg, p, sz, CHARS_CHAR);
+       if (NULL == ln)
+               return(-1);
+       return(ln->unicode);
+}
+
+
+/* 
+ * Reserved word to Unicode codepoint.
+ */
+int
+chars_res2cp(void *arg, const char *p, size_t sz)
+{
+       const struct ln *ln;
+
+       ln = find((struct tbl *)arg, p, sz, CHARS_STRING);
+       if (NULL == ln)
+               return(-1);
+       return(ln->unicode);
+}
+
+
+/* 
+ * Special character to string array.
+ */
 const char *
-chars_a2ascii(void *arg, const char *p, size_t sz, size_t *rsz)
+chars_spec2str(void *arg, const char *p, size_t sz, size_t *rsz)
 {
+       const struct ln *ln;
+
+       ln = find((struct tbl *)arg, p, sz, CHARS_CHAR);
+       if (NULL == ln)
+               return(NULL);
 
-       return(find((struct tbl *)arg, p, sz, rsz, CHARS_CHAR));
+       *rsz = ln->asciisz;
+       return(ln->ascii);
 }
 
 
+/* 
+ * Reserved word to string array.
+ */
 const char *
-chars_a2res(void *arg, const char *p, size_t sz, size_t *rsz)
+chars_res2str(void *arg, const char *p, size_t sz, size_t *rsz)
 {
+       const struct ln *ln;
+
+       ln = find((struct tbl *)arg, p, sz, CHARS_STRING);
+       if (NULL == ln)
+               return(NULL);
 
-       return(find((struct tbl *)arg, p, sz, rsz, CHARS_STRING));
+       *rsz = ln->asciisz;
+       return(ln->ascii);
 }
 
 
-static const char *
-find(struct tbl *tab, const char *p, size_t sz, size_t *rsz, int type)
+static const struct ln *
+find(struct tbl *tab, const char *p, size_t sz, int type)
 {
        struct ln        *pp, *prev;
        struct ln       **htab;
        int               hash;
 
        assert(p);
-       assert(sz > 0);
+       if (0 == sz)
+               return(NULL);
 
        if (p[0] < PRINT_LO || p[0] > PRINT_HI)
                return(NULL);
@@ -175,12 +221,7 @@ find(struct tbl *tab, const char *p, size_t sz, size_t *rsz, int type)
                        htab[hash] = pp;
                }
 
-               if (CHARS_HTML == tab->type) {
-                       *rsz = pp->htmlsz;
-                       return(pp->html);
-               }
-               *rsz = pp->asciisz;
-               return(pp->ascii);
+               return(pp);
        }
 
        return(NULL);
@@ -193,7 +234,7 @@ match(const struct ln *ln, const char *p, size_t sz, int type)
 
        if ( ! (ln->type & type))
                return(0);
-       if (ln->codesz != sz)
+       if (strncmp(ln->code, p, sz))
                return(0);
-       return(0 == strncmp(ln->code, p, sz));
+       return('\0' == ln->code[(int)sz]);
 }
index 8e55ed2..b050994 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: chars.h,v 1.4 2010/05/26 02:39:58 schwarze Exp $ */
+/*     $Id: chars.h,v 1.5 2010/07/25 18:05:54 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
@@ -25,8 +25,10 @@ enum chars {
 };
 
 void            *chars_init(enum chars);
-const char      *chars_a2ascii(void *, const char *, size_t, size_t *);
-const char      *chars_a2res(void *, const char *, size_t, size_t *);
+const char      *chars_spec2str(void *, const char *, size_t, size_t *);
+int              chars_spec2cp(void *, const char *, size_t);
+const char      *chars_res2str(void *, const char *, size_t, size_t *);
+int              chars_res2cp(void *, const char *, size_t);
 void             chars_free(void *);
 
 __END_DECLS
index 39e4992..ddb7729 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: chars.in,v 1.8 2010/06/06 20:30:08 schwarze Exp $ */
+/*     $Id: chars.in,v 1.9 2010/07/25 18:05:54 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * 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
@@ -36,411 +36,411 @@ static const char ascii_nbrsp[2] = { ASCII_NBRSP, 0 };
 CHAR_TBL_START
 
 /* Spacing. */
-CHAR("c",                      1,      "",             0,      "",             0)
-CHAR("0",                      1,      " ",            1,      "&#8194;",      7)
-CHAR(" ",                      1,      " ",            1,      "&#8194;",      7)
-CHAR("~",                      1,      ascii_nbrsp,    1,      "&#160;",       6)
-CHAR("%",                      1,      "",             0,      "",             0)
-CHAR("&",                      1,      "",             0,      "",             0)
-CHAR("^",                      1,      "",             0,      "",             0)
-CHAR("|",                      1,      "",             0,      "",             0)
-CHAR("}",                      1,      "",             0,      "",             0)
+CHAR("c",                      "",             0,      -1)
+CHAR("0",                      " ",            1,      8194)
+CHAR(" ",                      ascii_nbrsp,    1,      160)
+CHAR("~",                      ascii_nbrsp,    1,      160)
+CHAR("%",                      "",             0,      -1)
+CHAR("&",                      "",             0,      -1)
+CHAR("^",                      "",             0,      -1)
+CHAR("|",                      "",             0,      -1)
+CHAR("}",                      "",             0,      -1)
 
 /* Accents. */
-CHAR("a\"",                    2,      "\"",           1,      "&#779;",       6)
-CHAR("a-",                     2,      "-",            1,      "&#175;",       6)
-CHAR("a.",                     2,      ".",            1,      "&#729;",       6)
-CHAR("a^",                     2,      "^",            1,      "&#770;",       6)
-BOTH("\'",                     1,      "\'",           1,      "&#769;",       6)
-BOTH("aa",                     2,      "\'",           1,      "&#769;",       6)
-BOTH("ga",                     2,      "`",            1,      "&#768;",       6)
-BOTH("`",                      1,      "`",            1,      "&#768;",       6)
-CHAR("ab",                     2,      "`",            1,      "&#774;",       6)
-CHAR("ac",                     2,      ",",            1,      "&#807;",       6)
-CHAR("ad",                     2,      "\"",           1,      "&#776;",       6)
-CHAR("ah",                     2,      "v",            1,      "&#711;",       6)
-CHAR("ao",                     2,      "o",            1,      "&#730;",       6)
-CHAR("a~",                     2,      "~",            1,      "&#771;",       6)
-CHAR("ho",                     2,      ",",            1,      "&#808;",       6)
-CHAR("ha",                     2,      "^",            1,      "^",            1)
-CHAR("ti",                     2,      "~",            1,      "~",            1)
+CHAR("a\"",                    "\"",           1,      779)
+CHAR("a-",                     "-",            1,      175)
+CHAR("a.",                     ".",            1,      729)
+CHAR("a^",                     "^",            1,      770)
+BOTH("\'",                     "\'",           1,      769)
+BOTH("aa",                     "\'",           1,      769)
+BOTH("ga",                     "`",            1,      768)
+BOTH("`",                      "`",            1,      768)
+CHAR("ab",                     "`",            1,      774)
+CHAR("ac",                     ",",            1,      807)
+CHAR("ad",                     "\"",           1,      776)
+CHAR("ah",                     "v",            1,      711)
+CHAR("ao",                     "o",            1,      730)
+CHAR("a~",                     "~",            1,      771)
+CHAR("ho",                     ",",            1,      808)
+CHAR("ha",                     "^",            1,      94)
+CHAR("ti",                     "~",            1,      126)
 
 /* Quotes. */
-CHAR("Bq",                     2,      ",,",           2,      "&#8222;",      7)
-CHAR("bq",                     2,      ",",            1,      "&#8218;",      7)
-BOTH("lq",                     2,      "``",           2,      "&#8220;",      7)
-BOTH("rq",                     2,      "\'\'",         2,      "&#8221;",      7)
-CHAR("oq",                     2,      "`",            1,      "&#8216;",      7)
-CHAR("cq",                     2,      "\'",           1,      "&#8217;",      7)
-CHAR("aq",                     2,      "\'",           1,      "\'",           1)
-CHAR("dq",                     2,      "\"",           1,      "\"",           1)
-CHAR("Fo",                     2,      "<<",           2,      "&#171;",       6)
-CHAR("Fc",                     2,      ">>",           2,      "&#187;",       6)
-CHAR("fo",                     2,      "<",            1,      "&#8249;",      7)
-CHAR("fc",                     2,      ">",            1,      "&#8250;",      7)
+CHAR("Bq",                     ",,",           2,      8222)
+CHAR("bq",                     ",",            1,      8218)
+BOTH("lq",                     "``",           2,      8220)
+BOTH("rq",                     "\'\'",         2,      8221)
+CHAR("oq",                     "`",            1,      8216)
+CHAR("cq",                     "\'",           1,      8217)
+CHAR("aq",                     "\'",           1,      39)
+CHAR("dq",                     "\"",           1,      34)
+CHAR("Fo",                     "<<",           2,      171)
+CHAR("Fc",                     ">>",           2,      187)
+CHAR("fo",                     "<",            1,      8249)
+CHAR("fc",                     ">",            1,      8250)
 
 /* Brackets. */
-CHAR("lB",                     2,      "[",            1,      "[",            1)
-CHAR("rB",                     2,      "]",            1,      "]",            1)
-CHAR("lC",                     2,      "{",            1,      "{",            1)
-CHAR("rC",                     2,      "}",            1,      "}",            1)
-CHAR("la",                     2,      "<",            1,      "&#10216;",     8)
-CHAR("ra",                     2,      ">",            1,      "&#10217;",     8)
-CHAR("bv",                     2,      "|",            1,      "&#9130;",      7)
-CHAR("braceex",                        7,      "|",            1,      "&#9130;",      7)
-CHAR("bracketlefttp",          13,     "|",            1,      "&#9121;",      7)
-CHAR("bracketleftbp",          13,     "|",            1,      "&#9123;",      7)
-CHAR("bracketleftex",          13,     "|",            1,      "&#9122;",      7)
-CHAR("bracketrighttp",         14,     "|",            1,      "&#9124;",      7)
-CHAR("bracketrightbp",         14,     "|",            1,      "&#9126;",      7)
-CHAR("bracketrightex",         14,     "|",            1,      "&#9125;",      7)
-CHAR("lt",                     2,      ",-",           2,      "&#9127;",      7)
-CHAR("bracelefttp",            11,     ",-",           2,      "&#9127;",      7)
-CHAR("lk",                     2,      "{",            1,      "&#9128;",      7)
-CHAR("braceleftmid",           12,     "{",            1,      "&#9128;",      7)
-CHAR("lb",                     2,      ",-",           2,      "&#9129;",      7)
-CHAR("braceleftbp",            11,     "`-",           2,      "&#9129;",      7)
-CHAR("braceleftex",            11,     "|",            1,      "&#9130;",      7)
-CHAR("rt",                     2,      "-.",           2,      "&#9131;",      7)
-CHAR("bracerighttp",           12,     "-.",           2,      "&#9131;",      7)
-CHAR("rk",                     2,      "}",            1,      "&#9132;",      7)
-CHAR("bracerightmid",          13,     "}",            1,      "&#9132;",      7)
-CHAR("rb",                     2,      "-\'",          2,      "&#9133;",      7)
-CHAR("bracerightbp",           12,     "-\'",          2,      "&#9133;",      7)
-CHAR("bracerightex",           12,     "|",            1,      "&#9130;",      7)
-CHAR("parenlefttp",            11,     "/",            1,      "&#9115;",      7)
-CHAR("parenleftbp",            11,     "\\",           1,      "&#9117;",      7)
-CHAR("parenleftex",            11,     "|",            1,      "&#9116;",      7)
-CHAR("parenrighttp",           12,     "\\",           1,      "&#9118;",      7)
-CHAR("parenrightbp",           12,     "/",            1,      "&#9120;",      7)
-CHAR("parenrightex",           12,     "|",            1,      "&#9119;",      7)
+CHAR("lB",                     "[",            1,      91)
+CHAR("rB",                     "]",            1,      93)
+CHAR("lC",                     "{",            1,      123)
+CHAR("rC",                     "}",            1,      125)
+CHAR("la",                     "<",            1,      60)
+CHAR("ra",                     ">",            1,      62)
+CHAR("bv",                     "|",            1,      9130)
+CHAR("braceex",                        "|",            1,      9130)
+CHAR("bracketlefttp",          "|",            1,      9121)
+CHAR("bracketleftbp",          "|",            1,      9123)
+CHAR("bracketleftex",          "|",            1,      9122)
+CHAR("bracketrighttp",         "|",            1,      9124)
+CHAR("bracketrightbp",         "|",            1,      9126)
+CHAR("bracketrightex",         "|",            1,      9125)
+CHAR("lt",                     ",-",           2,      9127)
+CHAR("bracelefttp",            ",-",           2,      9127)
+CHAR("lk",                     "{",            1,      9128)
+CHAR("braceleftmid",           "{",            1,      9128)
+CHAR("lb",                     ",-",           2,      9129)
+CHAR("braceleftbp",            "`-",           2,      9129)
+CHAR("braceleftex",            "|",            1,      9130)
+CHAR("rt",                     "-.",           2,      9131)
+CHAR("bracerighttp",           "-.",           2,      9131)
+CHAR("rk",                     "}",            1,      9132)
+CHAR("bracerightmid",          "}",            1,      9132)
+CHAR("rb",                     "-\'",          2,      9133)
+CHAR("bracerightbp",           "-\'",          2,      9133)
+CHAR("bracerightex",           "|",            1,      9130)
+CHAR("parenlefttp",            "/",            1,      9115)
+CHAR("parenleftbp",            "\\",           1,      9117)
+CHAR("parenleftex",            "|",            1,      9116)
+CHAR("parenrighttp",           "\\",           1,      9118)
+CHAR("parenrightbp",           "/",            1,      9120)
+CHAR("parenrightex",           "|",            1,      9119)
 
 /* Greek characters. */
-CHAR("*A",                     2,      "A",            1,      "&#913;",       6)
-CHAR("*B",                     2,      "B",            1,      "&#914;",       6)
-CHAR("*G",                     2,      "|",            1,      "&#915;",       6)
-CHAR("*D",                     2,      "/\\",          2,      "&#916;",       6)
-CHAR("*E",                     2,      "E",            1,      "&#917;",       6)
-CHAR("*Z",                     2,      "Z",            1,      "&#918;",       6)
-CHAR("*Y",                     2,      "H",            1,      "&#919;",       6)
-CHAR("*H",                     2,      "O",            1,      "&#920;",       6)
-CHAR("*I",                     2,      "I",            1,      "&#921;",       6)
-CHAR("*K",                     2,      "K",            1,      "&#922;",       6)
-CHAR("*L",                     2,      "/\\",          2,      "&#923;",       6)
-CHAR("*M",                     2,      "M",            1,      "&#924;",       6)
-CHAR("*N",                     2,      "N",            1,      "&#925;",       6)
-CHAR("*C",                     2,      "H",            1,      "&#926;",       6)
-CHAR("*O",                     2,      "O",            1,      "&#927;",       6)
-CHAR("*P",                     2,      "TT",           2,      "&#928;",       6)
-CHAR("*R",                     2,      "P",            1,      "&#929;",       6)
-CHAR("*S",                     2,      ">",            1,      "&#931;",       6)
-CHAR("*T",                     2,      "T",            1,      "&#932;",       6)
-CHAR("*U",                     2,      "Y",            1,      "&#933;",       6)
-CHAR("*F",                     2,      "O_",           1,      "&#934;",       6)
-CHAR("*X",                     2,      "X",            1,      "&#935;",       6)
-CHAR("*Q",                     2,      "Y",            1,      "&#936;",       6)
-CHAR("*W",                     2,      "O",            1,      "&#937;",       6)
-CHAR("*a",                     2,      "a",            1,      "&#945;",       6)
-CHAR("*b",                     2,      "B",            1,      "&#946;",       6)
-CHAR("*g",                     2,      "y",            1,      "&#947;",       6)
-CHAR("*d",                     2,      "d",            1,      "&#948;",       6)
-CHAR("*e",                     2,      "e",            1,      "&#949;",       6)
-CHAR("*z",                     2,      "C",            1,      "&#950;",       6)
-CHAR("*y",                     2,      "n",            1,      "&#951;",       6)
-CHAR("*h",                     2,      "0",            1,      "&#952;",       6)
-CHAR("*i",                     2,      "i",            1,      "&#953;",       6)
-CHAR("*k",                     2,      "k",            1,      "&#954;",       6)
-CHAR("*l",                     2,      "\\",           1,      "&#955;",       6)
-CHAR("*m",                     2,      "u",            1,      "&#956;",       6)
-CHAR("*n",                     2,      "v",            1,      "&#957;",       6)
-CHAR("*c",                     2,      "E",            1,      "&#958;",       6)
-CHAR("*o",                     2,      "o",            1,      "&#959;",       6)
-CHAR("*p",                     2,      "n",            1,      "&#960;",       6)
-CHAR("*r",                     2,      "p",            1,      "&#961;",       6)
-CHAR("*s",                     2,      "o",            1,      "&#963;",       6)
-CHAR("*t",                     2,      "t",            1,      "&#964;",       6)
-CHAR("*u",                     2,      "u",            1,      "&#965;",       6)
-CHAR("*f",                     2,      "o",            1,      "&#981;",       6)
-CHAR("*x",                     2,      "x",            1,      "&#967;",       6)
-CHAR("*q",                     2,      "u",            1,      "&#968;",       6)
-CHAR("*w",                     2,      "w",            1,      "&#969;",       6)
-CHAR("+h",                     2,      "0",            1,      "&#977;",       6)
-CHAR("+f",                     2,      "o",            1,      "&#966;",       6)
-CHAR("+p",                     2,      "w",            1,      "&#982;",       6)
-CHAR("+e",                     2,      "e",            1,      "&#1013;",      7)
-CHAR("ts",                     2,      "s",            1,      "&#962;",       6)
+CHAR("*A",                     "A",            1,      913)
+CHAR("*B",                     "B",            1,      914)
+CHAR("*G",                     "|",            1,      915)
+CHAR("*D",                     "/\\",          2,      916)
+CHAR("*E",                     "E",            1,      917)
+CHAR("*Z",                     "Z",            1,      918)
+CHAR("*Y",                     "H",            1,      919)
+CHAR("*H",                     "O",            1,      920)
+CHAR("*I",                     "I",            1,      921)
+CHAR("*K",                     "K",            1,      922)
+CHAR("*L",                     "/\\",          2,      923)
+CHAR("*M",                     "M",            1,      924)
+CHAR("*N",                     "N",            1,      925)
+CHAR("*C",                     "H",            1,      926)
+CHAR("*O",                     "O",            1,      927)
+CHAR("*P",                     "TT",           2,      928)
+CHAR("*R",                     "P",            1,      929)
+CHAR("*S",                     ">",            1,      931)
+CHAR("*T",                     "T",            1,      932)
+CHAR("*U",                     "Y",            1,      933)
+CHAR("*F",                     "O_",           1,      934)
+CHAR("*X",                     "X",            1,      935)
+CHAR("*Q",                     "Y",            1,      936)
+CHAR("*W",                     "O",            1,      937)
+CHAR("*a",                     "a",            1,      945)
+CHAR("*b",                     "B",            1,      946)
+CHAR("*g",                     "y",            1,      947)
+CHAR("*d",                     "d",            1,      948)
+CHAR("*e",                     "e",            1,      949)
+CHAR("*z",                     "C",            1,      950)
+CHAR("*y",                     "n",            1,      951)
+CHAR("*h",                     "0",            1,      952)
+CHAR("*i",                     "i",            1,      953)
+CHAR("*k",                     "k",            1,      954)
+CHAR("*l",                     "\\",           1,      955)
+CHAR("*m",                     "u",            1,      956)
+CHAR("*n",                     "v",            1,      957)
+CHAR("*c",                     "E",            1,      958)
+CHAR("*o",                     "o",            1,      959)
+CHAR("*p",                     "n",            1,      960)
+CHAR("*r",                     "p",            1,      961)
+CHAR("*s",                     "o",            1,      963)
+CHAR("*t",                     "t",            1,      964)
+CHAR("*u",                     "u",            1,      965)
+CHAR("*f",                     "o",            1,      981)
+CHAR("*x",                     "x",            1,      967)
+CHAR("*q",                     "u",            1,      968)
+CHAR("*w",                     "w",            1,      969)
+CHAR("+h",                     "0",            1,      977)
+CHAR("+f",                     "o",            1,      966)
+CHAR("+p",                     "w",            1,      982)
+CHAR("+e",                     "e",            1,      1013)
+CHAR("ts",                     "s",            1,      962)
 
 /* Accented letters. */
-CHAR(",C",                     2,      "C",            1,      "&#199;",       6)
-CHAR(",c",                     2,      "c",            1,      "&#231;",       6)
-CHAR("/L",                     2,      "L",            1,      "&#321;",       6)
-CHAR("/O",                     2,      "O",            1,      "&#216;",       6)
-CHAR("/l",                     2,      "l",            1,      "&#322;",       6)
-CHAR("/o",                     2,      "o",            1,      "&#248;",       6)
-CHAR("oA",                     2,      "A",            1,      "&#197;",       6)
-CHAR("oa",                     2,      "a",            1,      "&#229;",       6)
-CHAR(":A",                     2,      "A",            1,      "&#196;",       6)
-CHAR(":E",                     2,      "E",            1,      "&#203;",       6)
-CHAR(":I",                     2,      "I",            1,      "&#207;",       6)
-CHAR(":O",                     2,      "O",            1,      "&#214;",       6)
-CHAR(":U",                     2,      "U",            1,      "&#220;",       6)
-CHAR(":a",                     2,      "a",            1,      "&#228;",       6)
-CHAR(":e",                     2,      "e",            1,      "&#235;",       6)
-CHAR(":i",                     2,      "i",            1,      "&#239;",       6)
-CHAR(":o",                     2,      "o",            1,      "&#245;",       6)
-CHAR(":u",                     2,      "u",            1,      "&#252;",       6)
-CHAR(":y",                     2,      "y",            1,      "&#255;",       6)
-CHAR("\'A",                    2,      "A",            1,      "&#193;",       6)
-CHAR("\'E",                    2,      "E",            1,      "&#201;",       6)
-CHAR("\'I",                    2,      "I",            1,      "&#205;",       6)
-CHAR("\'O",                    2,      "O",            1,      "&#211;",       6)
-CHAR("\'U",                    2,      "U",            1,      "&#218;",       6)
-CHAR("\'a",                    2,      "a",            1,      "&#225;",       6)
-CHAR("\'e",                    2,      "e",            1,      "&#233;",       6)
-CHAR("\'i",                    2,      "i",            1,      "&#237;",       6)
-CHAR("\'o",                    2,      "o",            1,      "&#243;",       6)
-CHAR("\'u",                    2,      "u",            1,      "&#250;",       6)
-CHAR("^A",                     2,      "A",            1,      "&#194;",       6)
-CHAR("^E",                     2,      "E",            1,      "&#202;",       6)
-CHAR("^I",                     2,      "I",            1,      "&#206;",       6)
-CHAR("^O",                     2,      "O",            1,      "&#212;",       6)
-CHAR("^U",                     2,      "U",            1,      "&#219;",       6)
-CHAR("^a",                     2,      "a",            1,      "&#226;",       6)
-CHAR("^e",                     2,      "e",            1,      "&#234;",       6)
-CHAR("^i",                     2,      "i",            1,      "&#238;",       6)
-CHAR("^o",                     2,      "o",            1,      "&#244;",       6)
-CHAR("^u",                     2,      "u",            1,      "&#251;",       6)
-CHAR("`A",                     2,      "A",            1,      "&#192;",       6)
-CHAR("`E",                     2,      "E",            1,      "&#200;",       6)
-CHAR("`I",                     2,      "I",            1,      "&#204;",       6)
-CHAR("`O",                     2,      "O",            1,      "&#210;",       6)
-CHAR("`U",                     2,      "U",            1,      "&#217;",       6)
-CHAR("`a",                     2,      "a",            1,      "&#224;",       6)
-CHAR("`e",                     2,      "e",            1,      "&#232;",       6)
-CHAR("`i",                     2,      "i",            1,      "&#236;",       6)
-CHAR("`o",                     2,      "o",            1,      "&#242;",       6)
-CHAR("`u",                     2,      "u",            1,      "&#249;",       6)
-CHAR("~A",                     2,      "A",            1,      "&#195;",       6)
-CHAR("~N",                     2,      "N",            1,      "&#209;",       6)
-CHAR("~O",                     2,      "O",            1,      "&#213;",       6)
-CHAR("~a",                     2,      "a",            1,      "&#227;",       6)
-CHAR("~n",                     2,      "n",            1,      "&#241;",       6)
-CHAR("~o",                     2,      "o",            1,      "&#245;",       6)
+CHAR(",C",                     "C",            1,      199)
+CHAR(",c",                     "c",            1,      231)
+CHAR("/L",                     "L",            1,      321)
+CHAR("/O",                     "O",            1,      216)
+CHAR("/l",                     "l",            1,      322)
+CHAR("/o",                     "o",            1,      248)
+CHAR("oA",                     "A",            1,      197)
+CHAR("oa",                     "a",            1,      229)
+CHAR(":A",                     "A",            1,      196)
+CHAR(":E",                     "E",            1,      203)
+CHAR(":I",                     "I",            1,      207)
+CHAR(":O",                     "O",            1,      214)
+CHAR(":U",                     "U",            1,      220)
+CHAR(":a",                     "a",            1,      228)
+CHAR(":e",                     "e",            1,      235)
+CHAR(":i",                     "i",            1,      239)
+CHAR(":o",                     "o",            1,      245)
+CHAR(":u",                     "u",            1,      252)
+CHAR(":y",                     "y",            1,      255)
+CHAR("\'A",                    "A",            1,      193)
+CHAR("\'E",                    "E",            1,      201)
+CHAR("\'I",                    "I",            1,      205)
+CHAR("\'O",                    "O",            1,      211)
+CHAR("\'U",                    "U",            1,      218)
+CHAR("\'a",                    "a",            1,      225)
+CHAR("\'e",                    "e",            1,      233)
+CHAR("\'i",                    "i",            1,      237)
+CHAR("\'o",                    "o",            1,      243)
+CHAR("\'u",                    "u",            1,      250)
+CHAR("^A",                     "A",            1,      194)
+CHAR("^E",                     "E",            1,      202)
+CHAR("^I",                     "I",            1,      206)
+CHAR("^O",                     "O",            1,      212)
+CHAR("^U",                     "U",            1,      219)
+CHAR("^a",                     "a",            1,      226)
+CHAR("^e",                     "e",            1,      234)
+CHAR("^i",                     "i",            1,      238)
+CHAR("^o",                     "o",            1,      244)
+CHAR("^u",                     "u",            1,      251)
+CHAR("`A",                     "A",            1,      192)
+CHAR("`E",                     "E",            1,      200)
+CHAR("`I",                     "I",            1,      204)
+CHAR("`O",                     "O",            1,      210)
+CHAR("`U",                     "U",            1,      217)
+CHAR("`a",                     "a",            1,      224)
+CHAR("`e",                     "e",            1,      232)
+CHAR("`i",                     "i",            1,      236)
+CHAR("`o",                     "o",            1,      242)
+CHAR("`u",                     "u",            1,      249)
+CHAR("~A",                     "A",            1,      195)
+CHAR("~N",                     "N",            1,      209)
+CHAR("~O",                     "O",            1,      213)
+CHAR("~a",                     "a",            1,      227)
+CHAR("~n",                     "n",            1,      241)
+CHAR("~o",                     "o",            1,      245)
 
 /* Arrows and lines. */
-CHAR("<-",                     2,      "<-",           2,      "&#8592;",      7)
-CHAR("->",                     2,      "->",           2,      "&#8594;",      7)
-CHAR("<>",                     2,      "<>",           2,      "&#8596;",      7)
-CHAR("da",                     2,      "v",            1,      "&#8595;",      7)
-BOTH("ua",                     2,      "^",            1,      "&#8593;",      7)
-BOTH("va",                     2,      "^v",           2,      "&#8597;",      7)
-CHAR("lA",                     2,      "<=",           2,      "&#8656;",      7)
-CHAR("rA",                     2,      "=>",           2,      "&#8658;",      7)
-CHAR("hA",                     2,      "<=>",          3,      "&#8660;",      7)
-CHAR("dA",                     2,      "v",            1,      "&#8659;",      7)
-CHAR("uA",                     2,      "^",            1,      "&#8657;",      7)
-CHAR("vA",                     2,      "^=v",          3,      "&#8661;",      7)
+CHAR("<-",                     "<-",           2,      8592)
+CHAR("->",                     "->",           2,      8594)
+CHAR("<>",                     "<>",           2,      8596)
+CHAR("da",                     "v",            1,      8595)
+BOTH("ua",                     "^",            1,      8593)
+BOTH("va",                     "^v",           2,      8597)
+CHAR("lA",                     "<=",           2,      8656)
+CHAR("rA",                     "=>",           2,      8658)
+CHAR("hA",                     "<=>",          3,      8660)
+CHAR("dA",                     "v",            1,      8659)
+CHAR("uA",                     "^",            1,      8657)
+CHAR("vA",                     "^=v",          3,      8661)
 
 /* Logic. */
-CHAR("AN",                     2,      "^",            1,      "&#8743;",      7)
-CHAR("OR",                     2,      "v",            1,      "&#8744;",      7)
-CHAR("no",                     2,      "~",            1,      "&#172;",       6)
-CHAR("tno",                    3,      "~",            1,      "&#172;",       6)
-CHAR("te",                     2,      "3",            1,      "&#8707;",      7)
-CHAR("fa",                     2,      "V",            1,      "&#8704;",      7)
-CHAR("st",                     2,      "-)",           2,      "&#8715;",      7)
-CHAR("tf",                     2,      ".:.",          3,      "&#8756;",      7)
-CHAR("3d",                     2,      ".:.",          3,      "&#8756;",      7)
-CHAR("or",                     2,      "|",            1,      "|",            1)
+CHAR("AN",                     "^",            1,      8743)
+CHAR("OR",                     "v",            1,      8744)
+CHAR("no",                     "~",            1,      172)
+CHAR("tno",                    "~",            1,      172)
+CHAR("te",                     "3",            1,      8707)
+CHAR("fa",                     "V",            1,      8704)
+CHAR("st",                     "-)",           2,      8715)
+CHAR("tf",                     ".:.",          3,      8756)
+CHAR("3d",                     ".:.",          3,      8756)
+CHAR("or",                     "|",            1,      124)
 
 /* Mathematicals. */
-CHAR("pl",                     2,      "+",            1,      "&#43;",        5)
-CHAR("mi",                     2,      "-",            1,      "&#8722;",      7)
-CHAR("-",                      1,      "-",            1,      "-",            1)
-CHAR("-+",                     2,      "-+",           2,      "&#8723;",      7)
-CHAR("+-",                     2,      "+-",           2,      "&#177;",       6)
-CHAR("t+-",                    3,      "+-",           2,      "&#177;",       6)
-CHAR("pc",                     2,      ".",            1,      "&#183;",       6)
-CHAR("md",                     2,      ".",            1,      "&#8901;",      7)
-CHAR("mu",                     2,      "x",            1,      "&#215;",       6)
-CHAR("tmu",                    3,      "x",            1,      "&#215;",       6)
-CHAR("c*",                     2,      "x",            1,      "&#8855;",      7)
-CHAR("c+",                     2,      "+",            1,      "&#8853;",      7)
-CHAR("di",                     2,      "-:-",          3,      "&#247;",       6)
-CHAR("tdi",                    3,      "-:-",          3,      "&#247;",       6)
-CHAR("f/",                     2,      "/",            1,      "&#8260;",      7)
-CHAR("**",                     2,      "*",            1,      "&#8727;",      7)
-BOTH("<=",                     2,      "<=",           2,      "&#8804;",      7)
-BOTH(">=",                     2,      ">=",           2,      "&#8805;",      7)
-CHAR("<<",                     2,      "<<",           2,      "&#8810;",      7)
-CHAR(">>",                     2,      ">>",           2,      "&#8811;",      7)
-CHAR("eq",                     2,      "=",            1,      "&#61;",        5)
-CHAR("!=",                     2,      "!=",           2,      "&#8800;",      7)
-CHAR("==",                     2,      "==",           2,      "&#8801;",      7)
-CHAR("ne",                     2,      "!==",          3,      "&#8802;",      7)
-CHAR("=~",                     2,      "=~",           2,      "&#8773;",      7)
-CHAR("-~",                     2,      "-~",           2,      "&#8771;",      7)
-CHAR("ap",                     2,      "~",            1,      "&#8764;",      7)
-CHAR("~~",                     2,      "~~",           2,      "&#8776;",      7)
-CHAR("~=",                     2,      "~=",           2,      "&#8780;",      7)
-CHAR("pt",                     2,      "oc",           2,      "&#8733;",      7)
-CHAR("es",                     2,      "{}",           2,      "&#8709;",      7)
-CHAR("mo",                     2,      "E",            1,      "&#8712;",      7)
-CHAR("nm",                     2,      "!E",           2,      "&#8713;",      7)
-CHAR("sb",                     2,      "(=",           2,      "&#8834;",      7)
-CHAR("nb",                     2,      "(!=",          3,      "&#8836;",      7)
-CHAR("sp",                     2,      "=)",           2,      "&#8835;",      7)
-CHAR("nc",                     2,      "!=)",          3,      "&#8837;",      7)
-CHAR("ib",                     2,      "(=",           2,      "&#8838;",      7)
-CHAR("ip",                     2,      "=)",           2,      "&#8839;",      7)
-CHAR("ca",                     2,      "(^)",          3,      "&#8745;",      7)
-CHAR("cu",                     2,      "U",            1,      "&#8746;",      7)
-CHAR("/_",                     2,      "/_",           2,      "&#8736;",      7)
-CHAR("pp",                     2,      "_|_",          3,      "&#8869;",      7)
-CHAR("is",                     2,      "I",            1,      "&#8747;",      7)
-CHAR("integral",               8,      "I",            1,      "&#8747;",      7)
-CHAR("sum",                    3,      "E",            1,      "&#8721;",      7)
-CHAR("product",                        7,      "TT",           2,      "&#8719;",      7)
-CHAR("coproduct",              9,      "U",            1,      "&#8720;",      7)
-CHAR("gr",                     2,      "V",            1,      "&#8711;",      7)
-CHAR("sr",                     2,      "\\/",          2,      "&#8730;",      7)
-CHAR("sqrt",                   4,      "\\/",          2,      "&#8730;",      7)
-CHAR("lc",                     2,      "|~",           2,      "&#8968;",      7)
-CHAR("rc",                     2,      "~|",           2,      "&#8969;",      7)
-CHAR("lf",                     2,      "|_",           2,      "&#8970;",      7)
-CHAR("rf",                     2,      "_|",           2,      "&#8971;",      7)
-CHAR("if",                     2,      "oo",           2,      "&#8734;",      7)
-CHAR("Ah",                     2,      "N",            1,      "&#8501;",      7)
-CHAR("Im",                     2,      "I",            1,      "&#8465;",      7)
-CHAR("Re",                     2,      "R",            1,      "&#8476;",      7)
-CHAR("pd",                     2,      "a",            1,      "&#8706;",      7)
-CHAR("-h",                     2,      "/h",           2,      "&#8463;",      7)
+CHAR("pl",                     "+",            1,      43)
+CHAR("mi",                     "-",            1,      8722)
+CHAR("-",                      "-",            1,      45)
+CHAR("-+",                     "-+",           2,      8723)
+CHAR("+-",                     "+-",           2,      177)
+CHAR("t+-",                    "+-",           2,      177)
+CHAR("pc",                     ".",            1,      183)
+CHAR("md",                     ".",            1,      8901)
+CHAR("mu",                     "x",            1,      215)
+CHAR("tmu",                    "x",            1,      215)
+CHAR("c*",                     "x",            1,      8855)
+CHAR("c+",                     "+",            1,      8853)
+CHAR("di",                     "-:-",          3,      247)
+CHAR("tdi",                    "-:-",          3,      247)
+CHAR("f/",                     "/",            1,      8260)
+CHAR("**",                     "*",            1,      8727)
+BOTH("<=",                     "<=",           2,      8804)
+BOTH(">=",                     ">=",           2,      8805)
+CHAR("<<",                     "<<",           2,      8810)
+CHAR(">>",                     ">>",           2,      8811)
+CHAR("eq",                     "=",            1,      61)
+CHAR("!=",                     "!=",           2,      8800)
+CHAR("==",                     "==",           2,      8801)
+CHAR("ne",                     "!==",          3,      8802)
+CHAR("=~",                     "=~",           2,      8773)
+CHAR("-~",                     "-~",           2,      8771)
+CHAR("ap",                     "~",            1,      8764)
+CHAR("~~",                     "~~",           2,      8776)
+CHAR("~=",                     "~=",           2,      8780)
+CHAR("pt",                     "oc",           2,      8733)
+CHAR("es",                     "{}",           2,      8709)
+CHAR("mo",                     "E",            1,      8712)
+CHAR("nm",                     "!E",           2,      8713)
+CHAR("sb",                     "(=",           2,      8834)
+CHAR("nb",                     "(!=",          3,      8836)
+CHAR("sp",                     "=)",           2,      8835)
+CHAR("nc",                     "!=)",          3,      8837)
+CHAR("ib",                     "(=",           2,      8838)
+CHAR("ip",                     "=)",           2,      8839)
+CHAR("ca",                     "(^)",          3,      8745)
+CHAR("cu",                     "U",            1,      8746)
+CHAR("/_",                     "/_",           2,      8736)
+CHAR("pp",                     "_|_",          3,      8869)
+CHAR("is",                     "I",            1,      8747)
+CHAR("integral",               "I",            1,      8747)
+CHAR("sum",                    "E",            1,      8721)
+CHAR("product",                        "TT",           2,      8719)
+CHAR("coproduct",              "U",            1,      8720)
+CHAR("gr",                     "V",            1,      8711)
+CHAR("sr",                     "\\/",          2,      8730)
+CHAR("sqrt",                   "\\/",          2,      8730)
+CHAR("lc",                     "|~",           2,      8968)
+CHAR("rc",                     "~|",           2,      8969)
+CHAR("lf",                     "|_",           2,      8970)
+CHAR("rf",                     "_|",           2,      8971)
+CHAR("if",                     "oo",           2,      8734)
+CHAR("Ah",                     "N",            1,      8501)
+CHAR("Im",                     "I",            1,      8465)
+CHAR("Re",                     "R",            1,      8476)
+CHAR("pd",                     "a",            1,      8706)
+CHAR("-h",                     "/h",           2,      8463)
 
 /* Ligatures. */
-CHAR("ff",                     2,      "ff",           2,      "&#64256;",     8)
-CHAR("fi",                     2,      "fi",           2,      "&#64257;",     8)
-CHAR("fl",                     2,      "fl",           2,      "&#64258;",     8)
-CHAR("Fi",                     2,      "ffi",          3,      "&#64259;",     8)
-CHAR("Fl",                     2,      "ffl",          3,      "&#64260;",     8)
-BOTH("AE",                     2,      "AE",           2,      "&#198;",       6)
-BOTH("ae",                     2,      "ae",           2,      "&#230;",       6)
-CHAR("OE",                     2,      "OE",           2,      "&#338;",       6)
-CHAR("oe",                     2,      "oe",           2,      "&#339;",       6)
-CHAR("ss",                     2,      "ss",           2,      "&#223;",       6)
-CHAR("IJ",                     2,      "IJ",           2,      "&#306;",       6)
-CHAR("ij",                     2,      "ij",           2,      "&#307;",       6)
+CHAR("ff",                     "ff",           2,      64256)
+CHAR("fi",                     "fi",           2,      64257)
+CHAR("fl",                     "fl",           2,      64258)
+CHAR("Fi",                     "ffi",          3,      64259)
+CHAR("Fl",                     "ffl",          3,      64260)
+BOTH("AE",                     "AE",           2,      198)
+BOTH("ae",                     "ae",           2,      230)
+CHAR("OE",                     "OE",           2,      338)
+CHAR("oe",                     "oe",           2,      339)
+CHAR("ss",                     "ss",           2,      223)
+CHAR("IJ",                     "IJ",           2,      306)
+CHAR("ij",                     "ij",           2,      307)
 
 /* Special letters. */
-CHAR("-D",                     2,      "D",            1,      "&#208;",       6)
-CHAR("Sd",                     2,      "o",            1,      "&#240;",       6)
-CHAR("TP",                     2,      "b",            1,      "&#222;",       6)
-CHAR("Tp",                     2,      "b",            1,      "&#254;",       6)
-CHAR(".i",                     2,      "i",            1,      "&#305;",       6)
-CHAR(".j",                     2,      "j",            1,      "&#567;",       6)
+CHAR("-D",                     "D",            1,      208)
+CHAR("Sd",                     "o",            1,      240)
+CHAR("TP",                     "b",            1,      222)
+CHAR("Tp",                     "b",            1,      254)
+CHAR(".i",                     "i",            1,      305)
+CHAR(".j",                     "j",            1,      567)
 
 /* Currency. */
-CHAR("Do",                     2,      "$",            1,      "$",            1)
-CHAR("ct",                     2,      "c",            1,      "&#162;",       6)
-CHAR("Eu",                     2,      "EUR",          3,      "&#8364;",      7)
-CHAR("eu",                     2,      "EUR",          3,      "&#8364;",      7)
-CHAR("Ye",                     2,      "Y",            1,      "&#165;",       6)
-CHAR("Po",                     2,      "L",            1,      "&#163;",       6)
-CHAR("Cs",                     2,      "x",            1,      "&#164;",       6)
-CHAR("Fn",                     2,      "f",            1,      "&#402;",       6)
+CHAR("Do",                     "$",            1,      36)
+CHAR("ct",                     "c",            1,      162)
+CHAR("Eu",                     "EUR",          3,      8364)
+CHAR("eu",                     "EUR",          3,      8364)
+CHAR("Ye",                     "Y",            1,      165)
+CHAR("Po",                     "L",            1,      163)
+CHAR("Cs",                     "x",            1,      164)
+CHAR("Fn",                     "f",            1,      402)
 
 /* pod2man holdovers. */
-STRING("--",                   2,      "--",           2,      "&#8212;",      7)
-STRING("PI",                   2,      "pi",           2,      "&#960;",       6)
-STRING("L\"",                  2,      "``",           2,      "&#8220;",      7)
-STRING("R\"",                  2,      "\'\'",         2,      "&#8221;",      7)
-STRING("C+",                   2,      "C++",          3,      "C++",          3)
-STRING("C`",                   2,      "`",            1,      "&#8216;",      7)
-STRING("C\'",                  2,      "\'",           1,      "&#8217;",      7)
-STRING("Aq",                   2,      "\'",           1,      "\'",           1)
-STRING("^",                    1,      "^",            1,      "^",            1)
-STRING(",",                    1,      ",",            1,      ",",            1)
-STRING("~",                    1,      "~",            1,      "~",            1)
-STRING("/",                    1,      "/",            1,      "/",            1)
-STRING(":",                    1,      "\"",           1,      "&#776;",       6)
-STRING("8",                    1,      "B",            1,      "&#946;",       6)
-STRING("o",                    1,      "o",            1,      "&#176;",       6)
-STRING("D-",                   2,      "D",            1,      "&#208;",       6)
-STRING("d-",                   2,      "o",            1,      "&#240;",       6)
-STRING("Th",                   2,      "b",            1,      "&#222;",       6)
-STRING("th",                   2,      "b",            1,      "&#254;",       6)
+STRING("--",                   "--",           2,      8212)
+STRING("PI",                   "pi",           2,      960)
+STRING("L\"",                  "``",           2,      8220)
+STRING("R\"",                  "\'\'",         2,      8221)
+STRING("C+",                   "C++",          3,      0)
+STRING("C`",                   "`",            1,      8216)
+STRING("C\'",                  "\'",           1,      8217)
+STRING("Aq",                   "\'",           1,      39)
+STRING("^",                    "^",            1,      94)
+STRING(",",                    ",",            1,      44)
+STRING("~",                    "~",            1,      126)
+STRING("/",                    "/",            1,      47)
+STRING(":",                    "\"",           1,      776)
+STRING("8",                    "B",            1,      946)
+STRING("o",                    "o",            1,      176)
+STRING("D-",                   "D",            1,      208)
+STRING("d-",                   "o",            1,      240)
+STRING("Th",                   "b",            1,      222)
+STRING("th",                   "b",            1,      254)
 
 /* Old style. */
-STRING("Am",                   2,      "&",            1,      "&amp;",        5)
-STRING("Ba",                   2,      "|",            1,      "|",            1)
-STRING("Ge",                   2,      ">=",           2,      "&#8805;",      7)
-STRING("Gt",                   2,      ">",            1,      "&gt;",         4)
-STRING("If",                   2,      "infinity",     8,      "infinity",     8)
-STRING("Le",                   2,      "<=",           2,      "&#8804;",      7)
-STRING("Lq",                   2,      "``",           2,      "&#8220;",      7)
-STRING("Lt",                   2,      "<",            1,      "&lt;",         4)
-STRING("Na",                   2,      "NaN",          3,      "NaN",          3)
-STRING("Ne",                   2,      "!=",           2,      "&#8800;",      7)
-STRING("Pi",                   2,      "pi",           2,      "&#960;",       6)
-STRING("Pm",                   2,      "+-",           2,      "&#177;",       6)
-STRING("R",                    1,      "(R)",          3,      "&#174;",       6)
-STRING("Rq",                   2,      "\'\'",         2,      "&#8221;",      7)
-STRING("Tm",                   2,      "tm",           2,      "&#8482;",      7)
-STRING("left-bracket",         12,     "[",            1,      "[",            1)
-STRING("left-parenthesis",     16,     "(",            1,      "(",            1)
-STRING("left-singlequote",     16,     "`",            1,      "&#8216;",      7)
-STRING("lp",                   2,      "(",            1,      "(",            1)
-STRING("q",                    1,      "\"",           1,      "&quot;",       6)
-STRING("quote-left",           10,     "`",            1,      "&#8216;",      7)
-STRING("quote-right",          11,     "\'",           1,      "&#8217;",      7)
-STRING("right-bracket",                13,     "]",            1,      "]",            1)
-STRING("right-parenthesis",    17,     ")",            1,      ")",            1)
-STRING("right-singlequote",    17,     "\'",           1,      "&#8217;",      7)
-STRING("rp",                   2,      ")",            1,      ")",            1)
+STRING("Am",                   "&",            1,      38)
+STRING("Ba",                   "|",            1,      124)
+STRING("Ge",                   ">=",           2,      8805)
+STRING("Gt",                   ">",            1,      62)
+STRING("If",                   "infinity",     8,      0)
+STRING("Le",                   "<=",           2,      8804)
+STRING("Lq",                   "``",           2,      8220)
+STRING("Lt",                   "<",            1,      60)
+STRING("Na",                   "NaN",          3,      0)
+STRING("Ne",                   "!=",           2,      8800)
+STRING("Pi",                   "pi",           2,      960)
+STRING("Pm",                   "+-",           2,      177)
+STRING("R",                    "(R)",          3,      174)
+STRING("Rq",                   "\'\'",         2,      8221)
+STRING("Tm",                   "tm",           2,      8482)
+STRING("left-bracket",         "[",            1,      91)
+STRING("left-parenthesis",     "(",            1,      40)
+STRING("left-singlequote",     "`",            1,      8216)
+STRING("lp",                   "(",            1,      40)
+STRING("q",                    "\"",           1,      34)
+STRING("quote-left",           "`",            1,      8216)
+STRING("quote-right",          "\'",           1,      8217)
+STRING("right-bracket",                "]",            1,      93)
+STRING("right-parenthesis",    ")",            1,      41)
+STRING("right-singlequote",    "\'",           1,      8217)
+STRING("rp",                   ")",            1,      41)
 
 /* Lines. */
-CHAR("ba",                     2,      "|",            1,      "&#124;",       6)
-CHAR("br",                     2,      "|",            1,      "&#9474;",      7)
-CHAR("ul",                     2,      "_",            1,      "&#95;",        5)
-CHAR("rl",                     2,      "-",            1,      "&#8254;",      7)
-CHAR("bb",                     2,      "|",            1,      "&#166;",       6)
-CHAR("sl",                     2,      "/",            1,      "&#47;",        5)
-CHAR("rs",                     2,      "\\",           1,      "&#92;",        5)
+CHAR("ba",                     "|",            1,      124)
+CHAR("br",                     "|",            1,      9474)
+CHAR("ul",                     "_",            1,      95)
+CHAR("rl",                     "-",            1,      8254)
+CHAR("bb",                     "|",            1,      166)
+CHAR("sl",                     "/",            1,      47)
+CHAR("rs",                     "\\",           1,      92)
 
 /* Text markers. */
-CHAR("ci",                     2,      "o",            1,      "&#9675;",      7)
-CHAR("bu",                     2,      "o",            1,      "&#8226;",      7)
-CHAR("dd",                     2,      "=",            1,      "&#8225;",      7)
-CHAR("dg",                     2,      "-",            1,      "&#8224;",      7)
-CHAR("lz",                     2,      "<>",           2,      "&#9674;",      7)
-CHAR("sq",                     2,      "[]",           2,      "&#9633;",      7)
-CHAR("ps",                     2,      "9|",           2,      "&#182;",       6)
-CHAR("sc",                     2,      "S",            1,      "&#167;",       6)
-CHAR("lh",                     2,      "<=",           2,      "&#9756;",      7)
-CHAR("rh",                     2,      "=>",           2,      "&#9758;",      7)
-CHAR("at",                     2,      "@",            1,      "&#64;",        5)
-CHAR("sh",                     2,      "#",            1,      "&#35;",        5)
-CHAR("CR",                     2,      "_|",           2,      "&#8629;",      7)
-CHAR("OK",                     2,      "\\/",          2,      "&#10003;",     8)
+CHAR("ci",                     "o",            1,      9675)
+CHAR("bu",                     "o",            1,      8226)
+CHAR("dd",                     "=",            1,      8225)
+CHAR("dg",                     "-",            1,      8224)
+CHAR("lz",                     "<>",           2,      9674)
+CHAR("sq",                     "[]",           2,      9633)
+CHAR("ps",                     "9|",           2,      182)
+CHAR("sc",                     "S",            1,      167)
+CHAR("lh",                     "<=",           2,      9756)
+CHAR("rh",                     "=>",           2,      9758)
+CHAR("at",                     "@",            1,      64)
+CHAR("sh",                     "#",            1,      35)
+CHAR("CR",                     "_|",           2,      8629)
+CHAR("OK",                     "\\/",          2,      10003)
 
 /* Legal symbols. */
-CHAR("co",                     2,      "(C)",          3,      "&#169;",       6)
-CHAR("rg",                     2,      "(R)",          3,      "&#174;",       6)
-CHAR("tm",                     2,      "tm",           2,      "&#8482;",      7)
+CHAR("co",                     "(C)",          3,      169)
+CHAR("rg",                     "(R)",          3,      174)
+CHAR("tm",                     "tm",           2,      8482)
 
 /* Punctuation. */
-CHAR(".",                      1,      ".",            1,      ".",            1)
-CHAR("r!",                     2,      "i",            1,      "&#161;",       6)
-CHAR("r?",                     2,      "c",            1,      "&#191;",       6)
-CHAR("em",                     2,      "--",           2,      "&#8212;",      7)
-CHAR("en",                     2,      "-",            1,      "&#8211;",      7)
-CHAR("hy",                     2,      "-",            1,      "&#8208;",      7)
-CHAR("e",                      1,      "\\",           1,      "\\",           1)
+CHAR(".",                      ".",            1,      46)
+CHAR("r!",                     "i",            1,      161)
+CHAR("r?",                     "c",            1,      191)
+CHAR("em",                     "--",           2,      8212)
+CHAR("en",                     "-",            1,      8211)
+CHAR("hy",                     "-",            1,      8208)
+CHAR("e",                      "\\",           1,      92)
 
 /* Units. */
-CHAR("de",                     2,      "o",            1,      "&#176;",       6)
-CHAR("%0",                     2,      "%o",           2,      "&#8240;",      7)
-CHAR("fm",                     2,      "\'",           1,      "&#8242;",      7)
-CHAR("sd",                     2,      "\"",           1,      "&#8243;",      7)
-CHAR("mc",                     2,      "mu",           2,      "&#181;",       6)
+CHAR("de",                     "o",            1,      176)
+CHAR("%0",                     "%o",           2,      8240)
+CHAR("fm",                     "\'",           1,      8242)
+CHAR("sd",                     "\"",           1,      8243)
+CHAR("mc",                     "mu",           2,      181)
 
 CHAR_TBL_END
index 16cdb29..eb9ebda 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: html.c,v 1.12 2010/07/13 01:09:12 schwarze Exp $ */
+/*     $Id: html.c,v 1.13 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -84,7 +84,8 @@ static        const char      *const htmlattrs[ATTR_MAX] = {
        "summary",
 };
 
-static void              print_spec(struct html *, const char *, size_t);
+static void              print_spec(struct html *, enum roffdeco,
+                               const char *, size_t);
 static void              print_res(struct html *, const char *, size_t);
 static void              print_ctag(struct html *, enum htmltag);
 static void              print_doctype(struct html *);
@@ -211,30 +212,41 @@ print_gen_head(struct html *h)
 
 
 static void
-print_spec(struct html *h, const char *p, size_t len)
+print_spec(struct html *h, enum roffdeco d, const char *p, size_t len)
 {
+       int              cp;
        const char      *rhs;
        size_t           sz;
 
-       rhs = chars_a2ascii(h->symtab, p, len, &sz);
-
-       if (NULL == rhs) 
+       if ((cp = chars_spec2cp(h->symtab, p, len)) > 0) {
+               printf("&#%d;", cp);
+               return;
+       } else if (-1 == cp && DECO_SSPECIAL == d) {
+               fwrite(p, 1, len, stdout);
+               return;
+       } else if (-1 == cp)
                return;
-       fwrite(rhs, 1, sz, stdout);
+
+       if (NULL != (rhs = chars_spec2str(h->symtab, p, len, &sz)))
+               fwrite(rhs, 1, sz, stdout);
 }
 
 
 static void
 print_res(struct html *h, const char *p, size_t len)
 {
+       int              cp;
        const char      *rhs;
        size_t           sz;
 
-       rhs = chars_a2res(h->symtab, p, len, &sz);
-
-       if (NULL == rhs)
+       if ((cp = chars_res2cp(h->symtab, p, len)) > 0) {
+               printf("&#%d;", cp);
+               return;
+       } else if (-1 == cp)
                return;
-       fwrite(rhs, 1, sz, stdout);
+
+       if (NULL != (rhs = chars_res2str(h->symtab, p, len, &sz)))
+               fwrite(rhs, 1, sz, stdout);
 }
 
 
@@ -330,8 +342,10 @@ print_encode(struct html *h, const char *p, int norecurse)
                case (DECO_RESERVED):
                        print_res(h, seq, sz);
                        break;
+               case (DECO_SSPECIAL):
+                       /* FALLTHROUGH */
                case (DECO_SPECIAL):
-                       print_spec(h, seq, sz);
+                       print_spec(h, deco, seq, sz);
                        break;
                case (DECO_PREVIOUS):
                        /* FALLTHROUGH */
@@ -399,6 +413,9 @@ print_otag(struct html *h, enum htmltag tag,
                                printf("&#160;");
                }
 
+       if ( ! (h->flags & HTML_NONOSPACE))
+               h->flags &= ~HTML_NOSPACE;
+
        /* Print out the tag name and attributes. */
 
        printf("<%s", htmltags[tag].name);
@@ -526,7 +543,8 @@ print_text(struct html *h, const char *word)
 
        assert(word);
        if ( ! print_encode(h, word, 0))
-               h->flags &= ~HTML_NOSPACE;
+               if ( ! (h->flags & HTML_NONOSPACE))
+                       h->flags &= ~HTML_NOSPACE;
 
        /* 
         * Note that we don't process the pipe: the parser sees it as
index bd97349..e719721 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: html.h,v 1.7 2010/07/13 01:09:12 schwarze Exp $ */
+/*     $Id: html.h,v 1.8 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -113,6 +113,7 @@ struct      html {
 #define        HTML_IGNDELIM    (1 << 1)
 #define        HTML_KEEP        (1 << 2)
 #define        HTML_PREKEEP     (1 << 3)
+#define        HTML_NONOSPACE   (1 << 4)
        struct tagq       tags;
        struct ordq       ords;
        void             *symtab;
index 53b4e7b..512581e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: main.c,v 1.42 2010/07/13 01:09:12 schwarze Exp $ */
+/*     $Id: main.c,v 1.43 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -20,6 +20,7 @@
 #include <sys/stat.h>
 
 #include <assert.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdint.h>
@@ -56,7 +57,8 @@ enum  outt {
        OUTT_HTML,
        OUTT_XHTML,
        OUTT_LINT,
-       OUTT_PS
+       OUTT_PS,
+       OUTT_PDF
 };
 
 struct curparse {
@@ -99,6 +101,7 @@ static       const char * const      mandocerrs[MANDOCERR_MAX] = {
        "list type must come first",
        "bad standard",
        "bad library",
+       "tab in non-literal context",
        "bad escape sequence",
        "unterminated quoted string",
        "argument requires the width argument",
@@ -480,6 +483,26 @@ fdesc(struct curparse *curp)
                                ++lnn;
                                break;
                        }
+
+                       /* 
+                        * Warn about bogus characters.  If you're using
+                        * non-ASCII encoding, you're screwing your
+                        * readers.  Since I'd rather this not happen,
+                        * I'll be helpful and drop these characters so
+                        * we don't display gibberish.  Note to manual
+                        * writers: use special characters.
+                        */
+
+                       if ( ! isgraph((u_char)blk.buf[i]) &&
+                                       ! isblank((u_char)blk.buf[i])) {
+                               if ( ! mmsg(MANDOCERR_BADCHAR, curp, 
+                                               lnn_start, pos, 
+                                               "ignoring byte"))
+                                       goto bailout;
+                               i++;
+                               continue;
+                       }
+
                        /* Trailing backslash is like a plain character. */
                        if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
                                if (pos >= (int)ln.sz)
@@ -597,9 +620,13 @@ fdesc(struct curparse *curp)
                        curp->outdata = ascii_alloc(curp->outopts);
                        curp->outfree = ascii_free;
                        break;
+               case (OUTT_PDF):
+                       curp->outdata = pdf_alloc(curp->outopts);
+                       curp->outfree = pspdf_free;
+                       break;
                case (OUTT_PS):
                        curp->outdata = ps_alloc(curp->outopts);
-                       curp->outfree = ps_free;
+                       curp->outfree = pspdf_free;
                        break;
                default:
                        break;
@@ -617,6 +644,8 @@ fdesc(struct curparse *curp)
                        curp->outman = tree_man;
                        curp->outmdoc = tree_mdoc;
                        break;
+               case (OUTT_PDF):
+                       /* FALLTHROUGH */
                case (OUTT_ASCII):
                        /* FALLTHROUGH */
                case (OUTT_PS):
@@ -751,6 +780,8 @@ toptions(struct curparse *curp, char *arg)
                curp->outtype = OUTT_XHTML;
        else if (0 == strcmp(arg, "ps"))
                curp->outtype = OUTT_PS;
+       else if (0 == strcmp(arg, "pdf"))
+               curp->outtype = OUTT_PDF;
        else {
                fprintf(stderr, "%s: Bad argument\n", arg);
                return(0);
index 7d38a72..2cb020d 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: main.h,v 1.6 2010/06/29 15:49:52 schwarze Exp $ */
+/*     $Id: main.h,v 1.7 2010/07/25 18:05:54 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * 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
@@ -44,8 +44,9 @@ void            tree_man(void *, const struct man *);
 void            *ascii_alloc(char *);
 void             ascii_free(void *);
 
+void            *pdf_alloc(char *);
 void            *ps_alloc(char *);
-void             ps_free(void *);
+void             pspdf_free(void *);
 
 void             terminal_mdoc(void *, const struct mdoc *);
 void             terminal_man(void *, const struct man *);
index cb994e8..95b1762 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man.c,v 1.37 2010/07/16 00:34:33 schwarze Exp $ */
+/*     $Id: man.c,v 1.38 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -37,6 +37,7 @@ const char *const __man_macronames[MAN_MAX] = {
        "nf",           "fi",           "r",            "RE",
        "RS",           "DT",           "UC",           "PD",
        "Sp",           "Vb",           "Ve",           "AT",
+       "in"
        };
 
 const  char * const *man_macronames = __man_macronames;
index b56a286..06fdc75 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man.h,v 1.24 2010/06/27 21:54:42 schwarze Exp $ */
+/*     $Id: man.h,v 1.25 2010/07/25 18:05:54 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
@@ -56,6 +56,7 @@ enum  mant {
        MAN_Vb,
        MAN_Ve,
        MAN_AT,
+       MAN_in,
        MAN_MAX
 };
 
index 8550faf..eda931b 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_action.c,v 1.23 2010/06/06 18:08:41 schwarze Exp $ */
+/*     $Id: man_action.c,v 1.24 2010/07/25 18:05:54 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
@@ -70,6 +70,7 @@ const struct actions man_actions[MAN_MAX] = {
        { post_nf }, /* Vb */
        { post_fi }, /* Ve */
        { post_AT }, /* AT */
+       { NULL }, /* in */
 };
 
 
index 8b77f12..b127639 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_html.c,v 1.17 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: man_html.c,v 1.18 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 
 #define        MAN_ARGS          const struct man_meta *m, \
                          const struct man_node *n, \
+                         struct mhtml *mh, \
                          struct html *h
 
+struct mhtml {
+       int               fl;
+#define        MANH_LITERAL     (1 << 0) /* literal context */
+};
+
 struct htmlman {
        int             (*pre)(MAN_ARGS);
        int             (*post)(MAN_ARGS);
@@ -54,6 +60,8 @@ static        int               a2width(const struct man_node *,
 static int               man_alt_pre(MAN_ARGS);
 static int               man_br_pre(MAN_ARGS);
 static int               man_ign_pre(MAN_ARGS);
+static int               man_in_pre(MAN_ARGS);
+static int               man_literal_pre(MAN_ARGS);
 static void              man_root_post(MAN_ARGS);
 static int               man_root_pre(MAN_ARGS);
 static int               man_B_pre(MAN_ARGS);
@@ -92,8 +100,8 @@ static       const struct htmlman mans[MAN_MAX] = {
        { NULL, NULL }, /* na */
        { NULL, NULL }, /* i */
        { man_br_pre, NULL }, /* sp */
-       { NULL, NULL }, /* nf */
-       { NULL, NULL }, /* fi */
+       { man_literal_pre, NULL }, /* nf */
+       { man_literal_pre, NULL }, /* fi */
        { NULL, NULL }, /* r */
        { NULL, NULL }, /* RE */
        { man_RS_pre, NULL }, /* RS */
@@ -101,9 +109,10 @@ static     const struct htmlman mans[MAN_MAX] = {
        { man_ign_pre, NULL }, /* UC */
        { man_ign_pre, NULL }, /* PD */
        { man_br_pre, NULL }, /* Sp */
-       { man_ign_pre, NULL }, /* Vb */
-       { NULL, NULL }, /* Ve */
+       { man_literal_pre, NULL }, /* Vb */
+       { man_literal_pre, NULL }, /* Ve */
        { man_ign_pre, NULL }, /* AT */
+       { man_in_pre, NULL }, /* in */
 };
 
 
@@ -112,13 +121,16 @@ html_man(void *arg, const struct man *m)
 {
        struct html     *h;
        struct tag      *t;
+       struct mhtml     mh;
 
        h = (struct html *)arg;
 
        print_gen_decls(h);
 
+       memset(&mh, 0, sizeof(struct mhtml));
+
        t = print_otag(h, TAG_HTML, 0, NULL);
-       print_man(man_meta(m), man_node(m), h);
+       print_man(man_meta(m), man_node(m), &mh, h);
        print_tagq(h, t);
 
        printf("\n");
@@ -133,7 +145,7 @@ print_man(MAN_ARGS)
 
        t = print_otag(h, TAG_HEAD, 0, NULL);
 
-       print_man_head(m, n, h);
+       print_man_head(m, n, mh, h);
        print_tagq(h, t);
        t = print_otag(h, TAG_BODY, 0, NULL);
 
@@ -141,7 +153,7 @@ print_man(MAN_ARGS)
        tag.val = "body";
        print_otag(h, TAG_DIV, 1, &tag);
 
-       print_man_nodelist(m, n, h);
+       print_man_nodelist(m, n, mh, h);
 
        print_tagq(h, t);
 }
@@ -165,9 +177,9 @@ static void
 print_man_nodelist(MAN_ARGS)
 {
 
-       print_man_node(m, n, h);
+       print_man_node(m, n, mh, h);
        if (n->next)
-               print_man_nodelist(m, n->next, h);
+               print_man_nodelist(m, n->next, mh, h);
 }
 
 
@@ -190,10 +202,14 @@ print_man_node(MAN_ARGS)
 
        switch (n->type) {
        case (MAN_ROOT):
-               child = man_root_pre(m, n, h);
+               child = man_root_pre(m, n, mh, h);
                break;
        case (MAN_TEXT):
                print_text(h, n->string);
+
+               if (MANH_LITERAL & mh->fl)
+                       print_otag(h, TAG_BR, 0, NULL);
+
                return;
        default:
                /* 
@@ -208,12 +224,12 @@ print_man_node(MAN_ARGS)
                        t = h->tags.head;
                }
                if (mans[n->tok].pre)
-                       child = (*mans[n->tok].pre)(m, n, h);
+                       child = (*mans[n->tok].pre)(m, n, mh, h);
                break;
        }
 
        if (child && n->child)
-               print_man_nodelist(m, n->child, h);
+               print_man_nodelist(m, n->child, mh, h);
 
        /* This will automatically close out any font scope. */
        print_stagq(h, t);
@@ -222,13 +238,13 @@ print_man_node(MAN_ARGS)
 
        switch (n->type) {
        case (MAN_ROOT):
-               man_root_post(m, n, h);
+               man_root_post(m, n, mh, h);
                break;
        case (MAN_TEXT):
                break;
        default:
                if (mans[n->tok].post)
-                       (*mans[n->tok].post)(m, n, h);
+                       (*mans[n->tok].post)(m, n, mh, h);
                break;
        }
 }
@@ -449,7 +465,7 @@ man_alt_pre(MAN_ARGS)
                 * closed out with the scope.
                 */
                t = print_ofont(h, fp);
-               print_man_node(m, nn, h);
+               print_man_node(m, nn, mh, h);
                print_tagq(h, t);
        }
 
@@ -643,10 +659,10 @@ man_IP_pre(MAN_ARGS)
 
        if (MAN_IP == n->tok)
                for (nn = n->child; nn->next; nn = nn->next)
-                       print_man_node(m, nn, h);
+                       print_man_node(m, nn, mh, h);
        if (MAN_TP == n->tok)
                for (nn = n->child->next; nn; nn = nn->next)
-                       print_man_node(m, nn, h);
+                       print_man_node(m, nn, mh, h);
 
        return(0);
 }
@@ -711,6 +727,37 @@ man_I_pre(MAN_ARGS)
 }
 
 
+/* ARGSUSED */
+static int
+man_literal_pre(MAN_ARGS)
+{
+
+       switch (n->tok) {
+       case (MAN_nf):
+               /* FALLTHROUGH */
+       case (MAN_Vb):
+               print_otag(h, TAG_BR, 0, NULL);
+               mh->fl |= MANH_LITERAL;
+               return(MAN_Vb != n->tok);
+       default:
+               mh->fl &= ~MANH_LITERAL;
+               break;
+       }
+
+       return(1);
+}
+
+
+/* ARGSUSED */
+static int
+man_in_pre(MAN_ARGS)
+{
+
+       print_otag(h, TAG_BR, 0, NULL);
+       return(0);
+}
+
+
 /* ARGSUSED */
 static int
 man_ign_pre(MAN_ARGS)
index 84541d3..7e01af8 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_macro.c,v 1.19 2010/05/23 22:45:00 schwarze Exp $ */
+/*     $Id: man_macro.c,v 1.20 2010/07/25 18:05:54 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
@@ -79,6 +79,7 @@ const struct man_macro __man_macros[MAN_MAX] = {
        { in_line_eoln, 0 }, /* Vb */
        { in_line_eoln, 0 }, /* Ve */
        { in_line_eoln, 0 }, /* AT */
+       { in_line_eoln, 0 }, /* in */
 };
 
 const  struct man_macro * const man_macros = __man_macros;
@@ -286,6 +287,7 @@ blk_close(MACRO_PROT_ARGS)
 }
 
 
+/* ARGSUSED */
 int
 blk_exp(MACRO_PROT_ARGS)
 {
@@ -337,6 +339,7 @@ blk_exp(MACRO_PROT_ARGS)
  * scopes, such as `SH' closing out an `SS', are defined in the rew
  * routines.
  */
+/* ARGSUSED */
 int
 blk_imp(MACRO_PROT_ARGS)
 {
@@ -394,6 +397,7 @@ blk_imp(MACRO_PROT_ARGS)
 }
 
 
+/* ARGSUSED */
 int
 in_line_eoln(MACRO_PROT_ARGS)
 {
index dfb4463..9c3389d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: man_term.c,v 1.44 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: man_term.c,v 1.45 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -88,10 +88,9 @@ static       int               pre_RS(DECL_ARGS);
 static int               pre_SH(DECL_ARGS);
 static int               pre_SS(DECL_ARGS);
 static int               pre_TP(DECL_ARGS);
-static int               pre_br(DECL_ARGS);
-static int               pre_fi(DECL_ARGS);
 static int               pre_ign(DECL_ARGS);
-static int               pre_nf(DECL_ARGS);
+static int               pre_in(DECL_ARGS);
+static int               pre_literal(DECL_ARGS);
 static int               pre_sp(DECL_ARGS);
 
 static void              post_IP(DECL_ARGS);
@@ -102,7 +101,7 @@ static      void              post_SS(DECL_ARGS);
 static void              post_TP(DECL_ARGS);
 
 static const struct termact termacts[MAN_MAX] = {
-       { pre_br, NULL, MAN_NOTEXT }, /* br */
+       { pre_sp, NULL, MAN_NOTEXT }, /* br */
        { NULL, NULL, 0 }, /* TH */
        { pre_SH, post_SH, 0 }, /* SH */
        { pre_SS, post_SS, 0 }, /* SS */
@@ -126,8 +125,8 @@ static      const struct termact termacts[MAN_MAX] = {
        { NULL, NULL, MAN_NOTEXT }, /* na */
        { pre_I, NULL, 0 }, /* i */
        { pre_sp, NULL, MAN_NOTEXT }, /* sp */
-       { pre_nf, NULL, 0 }, /* nf */
-       { pre_fi, NULL, 0 }, /* fi */
+       { pre_literal, NULL, 0 }, /* nf */
+       { pre_literal, NULL, 0 }, /* fi */
        { NULL, NULL, 0 }, /* r */
        { NULL, NULL, 0 }, /* RE */
        { pre_RS, post_RS, 0 }, /* RS */
@@ -135,9 +134,10 @@ static     const struct termact termacts[MAN_MAX] = {
        { pre_ign, NULL, 0 }, /* UC */
        { pre_ign, NULL, 0 }, /* PD */
        { pre_sp, NULL, MAN_NOTEXT }, /* Sp */
-       { pre_nf, NULL, 0 }, /* Vb */
-       { pre_fi, NULL, 0 }, /* Ve */
+       { pre_literal, NULL, 0 }, /* Vb */
+       { pre_literal, NULL, 0 }, /* Ve */
        { pre_ign, NULL, 0 }, /* AT */
+       { pre_in, NULL, MAN_NOTEXT }, /* in */
 };
 
 
@@ -245,23 +245,25 @@ pre_I(DECL_ARGS)
 
 /* ARGSUSED */
 static int
-pre_fi(DECL_ARGS)
+pre_literal(DECL_ARGS)
 {
 
-       mt->fl &= ~MANT_LITERAL;
+       term_newln(p);
+       switch (n->tok) {
+       case (MAN_Vb):
+               /* FALLTHROUGH */
+       case (MAN_nf):
+               mt->fl |= MANT_LITERAL;
+               return(MAN_Vb != n->tok);
+       default:
+               mt->fl &= ~MANT_LITERAL;
+               break;
+       }
+
        return(1);
 }
 
 
-/* ARGSUSED */
-static int
-pre_nf(DECL_ARGS)
-{
-
-       mt->fl |= MANT_LITERAL;
-       return(MAN_Vb != n->tok);
-}
-
 
 /* ARGSUSED */
 static int
@@ -349,17 +351,40 @@ pre_B(DECL_ARGS)
 
 /* ARGSUSED */
 static int
-pre_sp(DECL_ARGS)
+pre_in(DECL_ARGS)
 {
-       size_t           i, len;
+       int              len, less;
+       size_t           v;
+       const char      *cp;
 
-       len = n->child ? 
-               a2height(p, n->child->string) : term_len(p, 1);
+       term_newln(p);
 
-       if (0 == len)
-               term_newln(p);
-       for (i = 0; i <= len; i++)
-               term_vspace(p);
+       if (NULL == n->child) {
+               p->offset = mt->offset;
+               return(0);
+       }
+
+       cp = n->child->string;
+       less = 0;
+
+       if ('-' == *cp)
+               less = -1;
+       else if ('+' == *cp)
+               less = 1;
+       else
+               cp--;
+
+       if ((len = a2width(p, ++cp)) < 0)
+               return(0);
+
+       v = (size_t)len;
+
+       if (less < 0)
+               p->offset -= p->offset > v ? v : p->offset;
+       else if (less > 0)
+               p->offset += v;
+       else 
+               p->offset = v;
 
        return(0);
 }
@@ -367,10 +392,24 @@ pre_sp(DECL_ARGS)
 
 /* ARGSUSED */
 static int
-pre_br(DECL_ARGS)
+pre_sp(DECL_ARGS)
 {
+       size_t           i, len;
+
+       switch (n->tok) {
+       case (MAN_br):
+               len = 0;
+               break;
+       default:
+               len = n->child ? a2height(p, n->child->string) : 1;
+               break;
+       }
+
+       if (0 == len)
+               term_newln(p);
+       for (i = 0; i < len; i++)
+               term_vspace(p);
 
-       term_newln(p);
        return(0);
 }
 
index 8658846..cb7ab9b 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: man_validate.c,v 1.27 2010/06/26 17:56:43 schwarze Exp $ */
+/*     $Id: man_validate.c,v 1.28 2010/07/25 18:05:54 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
@@ -22,6 +22,7 @@
 #include <limits.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "mandoc.h"
 #include "libman.h"
@@ -78,9 +79,9 @@ static        const struct man_valid man_valids[MAN_MAX] = {
        { NULL, NULL }, /* I */
        { NULL, NULL }, /* IR */
        { NULL, NULL }, /* RI */
-       { NULL, posts_eq0 }, /* na */
+       { NULL, posts_eq0 }, /* na */ /* FIXME: should warn only. */
        { NULL, NULL }, /* i */
-       { NULL, posts_le1 }, /* sp */
+       { NULL, posts_le1 }, /* sp */ /* FIXME: should warn only. */
        { pres_bline, posts_eq0 }, /* nf */
        { pres_bline, posts_eq0 }, /* fi */
        { NULL, NULL }, /* r */
@@ -89,10 +90,11 @@ static      const struct man_valid man_valids[MAN_MAX] = {
        { NULL, NULL }, /* DT */
        { NULL, NULL }, /* UC */
        { NULL, NULL }, /* PD */
-       { NULL, posts_le1 }, /* Sp */
-       { pres_bline, posts_le1 }, /* Vb */
+       { NULL, posts_le1 }, /* Sp */ /* FIXME: should warn only. */
+       { pres_bline, posts_le1 }, /* Vb */ /* FIXME: should warn only. */
        { pres_bline, posts_eq0 }, /* Ve */
        { NULL, NULL }, /* AT */
+       { NULL, NULL }, /* in */
 };
 
 
@@ -202,27 +204,37 @@ check_text(CHKARGS)
 {
        char            *p;
        int              pos, c;
-
-       assert(n->string);
+       size_t           sz;
 
        for (p = n->string, pos = n->pos + 1; *p; p++, pos++) {
-               if ('\\' == *p) {
-                       c = mandoc_special(p);
-                       if (c) {
-                               p += c - 1;
-                               pos += c - 1;
-                               continue;
-                       }
+               sz = strcspn(p, "\t\\");
+               p += (int)sz;
+
+               if ('\0' == *p)
+                       break;
+
+               pos += (int)sz;
 
-                       c = man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
-                       if ( ! (MAN_IGN_ESCAPE & m->pflags) && ! c)
-                               return(c);
+               if ('\t' == *p) {
+                       if (MAN_LITERAL & m->flags)
+                               continue;
+                       if (man_pmsg(m, n->line, pos, MANDOCERR_BADTAB))
+                               continue;
+                       return(0);
                }
 
-               if ('\t' == *p || isprint((u_char)*p) || ASCII_HYPH == *p) 
+               /* Check the special character. */
+
+               c = mandoc_special(p);
+               if (c) {
+                       p += c - 1;
+                       pos += c - 1;
                        continue;
-               if ( ! man_pmsg(m, n->line, pos, MANDOCERR_BADCHAR))
-                       return(0);
+               }
+
+               c = man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
+               if ( ! (MAN_IGN_ESCAPE & m->pflags) && ! c)
+                       return(c);
        }
 
        return(1);
index e0fa0b1..fb7b4db 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: mandoc.1,v 1.35 2010/07/13 01:09:13 schwarze Exp $
+.\"    $OpenBSD: mandoc.1,v 1.36 2010/07/25 18:05:54 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: July 13 2010 $
+.Dd $Mdocdate: July 25 2010 $
 .Dt MANDOC 1
 .Os
 .Sh NAME
@@ -192,6 +192,10 @@ Implies
 .Fl W Ns Cm all
 and
 .Fl f Ns Cm strict .
+.It Fl T Ns Cm pdf
+Produce PDF output.
+See
+.Sx PDF Output .
 .It Fl T Ns Cm ps
 Produce PostScript output.
 See
@@ -331,6 +335,14 @@ If an unknown value is encountered,
 .Ar letter
 is used.
 .El
+.Ss PDF Output
+PDF-1.1 output may be generated by
+.Fl T Ns Cm pdf .
+See
+.Sx PostScript Output
+for
+.Fl O
+arguments and defaults.
 .Ss XHTML Output
 Output produced by
 .Fl T Ns Cm xhtml
index aeef291..68d3451 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.c,v 1.15 2010/07/16 00:34:33 schwarze Exp $ */
+/*     $Id: mandoc.c,v 1.16 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 #include "libmandoc.h"
 
 static int      a2time(time_t *, const char *, const char *);
-static int      spec_norm(char *, int);
-
-
-/*
- * "Normalise" a special string by converting its ASCII_HYPH entries
- * into actual hyphens.
- */
-static int
-spec_norm(char *p, int sz)
-{
-       int              i;
-
-       for (i = 0; i < sz; i++)
-               if (ASCII_HYPH == p[i])
-                       p[i] = '-';
-
-       return(sz);
-}
 
 
 int
 mandoc_special(char *p)
 {
-       int              terminator;    /* Terminator for \s. */
-       int              lim;           /* Limit for N in \s. */
-       int              c, i;
+       int              len, i;
+       char             term;
        char            *sv;
        
+       len = 0;
+       term = '\0';
        sv = p;
 
-       if ('\\' != *p++)
-               return(spec_norm(sv, 0));
+       assert('\\' == *p);
+       p++;
 
-       switch (*p) {
-       case ('\''):
+       switch (*p++) {
+#if 0
+       case ('Z'):
+               /* FALLTHROUGH */
+       case ('X'):
+               /* FALLTHROUGH */
+       case ('x'):
                /* FALLTHROUGH */
-       case ('`'):
+       case ('w'):
                /* FALLTHROUGH */
-       case ('q'):
+       case ('v'):
                /* FALLTHROUGH */
-       case (ASCII_HYPH):
+       case ('S'):
                /* FALLTHROUGH */
-       case ('-'):
+       case ('R'):
                /* FALLTHROUGH */
-       case ('~'):
+       case ('o'):
                /* FALLTHROUGH */
-       case ('^'):
+       case ('N'):
                /* FALLTHROUGH */
-       case ('%'):
+       case ('l'):
                /* FALLTHROUGH */
-       case ('0'):
+       case ('L'):
                /* FALLTHROUGH */
-       case (' '):
+       case ('H'):
                /* FALLTHROUGH */
-       case ('}'):
+       case ('h'):
                /* FALLTHROUGH */
-       case ('|'):
+       case ('D'):
                /* FALLTHROUGH */
-       case ('&'):
+       case ('C'):
                /* FALLTHROUGH */
-       case ('.'):
+       case ('b'):
                /* FALLTHROUGH */
-       case (':'):
+       case ('B'):
                /* FALLTHROUGH */
-       case ('c'):
+       case ('a'):
                /* FALLTHROUGH */
-       case ('e'):
-               return(spec_norm(sv, 2));
+       case ('A'):
+               if (*p++ != '\'')
+                       return(0);
+               term = '\'';
+               break;
+#endif
        case ('s'):
-               if ('\0' == *++p)
-                       return(spec_norm(sv, 2));
-
-               c = 2;
-               terminator = 0;
-               lim = 1;
-
-               if (*p == '\'') {
-                       lim = 0;
-                       terminator = 1;
-                       ++p;
-                       ++c;
-               } else if (*p == '[') {
-                       lim = 0;
-                       terminator = 2;
-                       ++p;
-                       ++c;
-               } else if (*p == '(') {
-                       lim = 2;
-                       terminator = 3;
-                       ++p;
-                       ++c;
-               }
-
-               if (*p == '+' || *p == '-') {
-                       ++p;
-                       ++c;
-               }
-
-               if (*p == '\'') {
-                       if (terminator)
-                               return(spec_norm(sv, 0));
-                       lim = 0;
-                       terminator = 1;
-                       ++p;
-                       ++c;
-               } else if (*p == '[') {
-                       if (terminator)
-                               return(spec_norm(sv, 0));
-                       lim = 0;
-                       terminator = 2;
-                       ++p;
-                       ++c;
-               } else if (*p == '(') {
-                       if (terminator)
-                               return(spec_norm(sv, 0));
-                       lim = 2;
-                       terminator = 3;
-                       ++p;
-                       ++c;
-               }
+               if (ASCII_HYPH == *p)
+                       *p = '-';
+               if ('+' == *p || '-' == *p)
+                       p++;
 
-               /* TODO: needs to handle floating point. */
+               i = ('s' != *(p - 1));
 
-               if ( ! isdigit((u_char)*p))
-                       return(spec_norm(sv, 0));
-
-               for (i = 0; isdigit((u_char)*p); i++) {
-                       if (lim && i >= lim)
-                               break;
-                       ++p;
-                       ++c;
-               }
-
-               if (terminator && terminator < 3) {
-                       if (1 == terminator && *p != '\'')
-                               return(spec_norm(sv, 0));
-                       if (2 == terminator && *p != ']')
-                               return(spec_norm(sv, 0));
-                       ++p;
-                       ++c;
+               switch (*p++) {
+               case ('('):
+                       len = 2;
+                       break;
+               case ('['):
+                       term = ']';
+                       break;
+               case ('\''):
+                       term = '\'';
+                       break;
+               case ('0'):
+                       i++;
+                       /* FALLTHROUGH */
+               default:
+                       len = 1;
+                       p--;
+                       break;
                }
 
-               return(spec_norm(sv, c));
+               if (ASCII_HYPH == *p)
+                       *p = '-';
+               if ('+' == *p || '-' == *p) {
+                       if (i++)
+                               return(0);
+                       p++;
+               } 
+               
+               if (0 == i)
+                       return(0);
+               break;
+#if 0
+       case ('Y'):
+               /* FALLTHROUGH */
+       case ('V'):
+               /* FALLTHROUGH */
+       case ('$'):
+               /* FALLTHROUGH */
+       case ('n'):
+               /* FALLTHROUGH */
+       case ('k'):
+               /* FALLTHROUGH */
+#endif
+       case ('M'):
+               /* FALLTHROUGH */
+       case ('m'):
+               /* FALLTHROUGH */
        case ('f'):
                /* FALLTHROUGH */
        case ('F'):
                /* FALLTHROUGH */
        case ('*'):
-               if ('\0' == *++p || isspace((u_char)*p))
-                       return(spec_norm(sv, 0));
-               switch (*p) {
+               switch (*p++) {
                case ('('):
-                       if ('\0' == *++p || isspace((u_char)*p))
-                               return(spec_norm(sv, 0));
-                       return(spec_norm(sv, 4));
+                       len = 2;
+                       break;
                case ('['):
-                       for (c = 3, p++; *p && ']' != *p; p++, c++)
-                               if (isspace((u_char)*p))
-                                       break;
-                       return(spec_norm(sv, *p == ']' ? c : 0));
+                       term = ']';
+                       break;
                default:
+                       len = 1;
+                       p--;
                        break;
                }
-               return(spec_norm(sv, 3));
+               break;
        case ('('):
-               if ('\0' == *++p || isspace((u_char)*p))
-                       return(spec_norm(sv, 0));
-               if ('\0' == *++p || isspace((u_char)*p))
-                       return(spec_norm(sv, 0));
-               return(spec_norm(sv, 4));
+               len = 2;
+               break;
        case ('['):
+               term = ']';
                break;
        default:
-               return(spec_norm(sv, 0));
+               len = 1;
+               p--;
+               break;
        }
 
-       for (c = 3, p++; *p && ']' != *p; p++, c++)
-               if (isspace((u_char)*p))
-                       break;
+       if (term) {
+               for ( ; *p && term != *p; p++)
+                       if (ASCII_HYPH == *p)
+                               *p = '-';
+               return(*p ? (int)(p - sv) : 0);
+       }
 
-       return(spec_norm(sv, *p == ']' ? c : 0));
+       for (i = 0; *p && i < len; i++, p++)
+               if (ASCII_HYPH == *p)
+                       *p = '-';
+       return(i == len ? (int)(p - sv) : 0);
 }
 
 
@@ -327,7 +301,7 @@ int
 mandoc_eos(const char *p, size_t sz, int enclosed)
 {
        const char *q;
-       int found = 0;
+       int found;
 
        if (0 == sz)
                return(0);
@@ -338,7 +312,8 @@ mandoc_eos(const char *p, size_t sz, int enclosed)
         * propogate outward.
         */
 
-       for (q = p + sz - 1; q >= p; q--) {
+       found = 0;
+       for (q = p + (int)sz - 1; q >= p; q--) {
                switch (*q) {
                case ('\"'):
                        /* FALLTHROUGH */
index 53b239b..eb79fc6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mandoc.h,v 1.10 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: mandoc.h,v 1.11 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -39,6 +39,7 @@ enum  mandocerr {
        MANDOCERR_LISTFIRST, /* list type must come first */
        MANDOCERR_BADSTANDARD, /* bad standard */
        MANDOCERR_BADLIB, /* bad library */
+       MANDOCERR_BADTAB, /* tab in non-literal context */
        MANDOCERR_BADESCAPE, /* bad escape sequence */
        MANDOCERR_BADQUOTE, /* unterminated quoted string */
        MANDOCERR_NOWIDTHARG, /* argument requires the width argument */
index e00564a..1d64e58 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $Id: mdoc.7,v 1.40 2010/07/15 23:46:58 schwarze Exp $
+.\"    $Id: mdoc.7,v 1.41 2010/07/25 18:05:54 schwarze Exp $
 .\"
 .\" Copyright (c) 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
 .\" Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -15,7 +15,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: July 15 2010 $
+.Dd $Mdocdate: July 25 2010 $
 .Dt MDOC 7
 .Os
 .Sh NAME
@@ -27,8 +27,10 @@ The
 language is used to format
 .Bx
 .Ux
-manuals.  In this reference document, we describe its syntax, structure,
-and usage.  Our reference implementation is mandoc; the
+manuals.
+In this reference document, we describe its syntax, structure, and
+usage.
+Our reference implementation is mandoc; the
 .Sx COMPATIBILITY
 section describes compatibility with other troff \-mdoc implementations.
 .Pp
@@ -37,7 +39,8 @@ An
 document follows simple rules: lines beginning with the control
 character
 .Sq \.
-are parsed for macros.  Other lines are interpreted within the scope of
+are parsed for macros.
+Other lines are interpreted within the scope of
 prior macros:
 .Bd -literal -offset indent
 \&.Sh Macro lines change control state.
@@ -46,18 +49,20 @@ Other lines are interpreted within the current state.
 .Sh LANGUAGE SYNTAX
 .Nm
 documents may contain only graphable 7-bit ASCII characters, the space
-character, and, in certain circumstances, the tab character.  All
-manuals must have
+character, and, in certain circumstances, the tab character.
+All manuals must have
 .Ux
 line terminators.
 .Ss Comments
 Text following a
-.Sq \e" ,
+.Sq \e\*q ,
 whether in a macro or free-form text line, is ignored to the end of
-line.  A macro line with only a control character and comment escape,
-.Sq \&.\e" ,
-is also ignored.  Macro lines with only a control character and optionally
-whitespace are stripped from input.
+line.
+A macro line with only a control character and comment escape,
+.Sq \&.\e\*q ,
+is also ignored.
+Macro lines with only a control character and optionally whitespace are
+stripped from input.
 .Ss Reserved Characters
 Within a macro line, the following characters are reserved:
 .Pp
@@ -466,8 +471,8 @@ section, particularly
 .Sx \&Vt ,
 and
 .Sx \&Ft .
-All of these macros are output on their own line.  If two such
-dissimilar macros are pair-wise invoked (except for
+All of these macros are output on their own line.
+If two such dissimilar macros are pair-wise invoked (except for
 .Sx \&Ft
 before
 .Sx \&Fo
@@ -879,14 +884,17 @@ For the scoping of individual macros, see
 .Ss \&%A
 Author name of an
 .Sx \&Rs
-block.  Multiple authors should each be accorded their own
+block.
+Multiple authors should each be accorded their own
 .Sx \%%A
-line.  Author names should be ordered with full or abbreviated
-forename(s) first, then full surname.
+line.
+Author names should be ordered with full or abbreviated forename(s)
+first, then full surname.
 .Ss \&%B
 Book title of an
 .Sx \&Rs
-block.  This macro may also be used in a non-bibliographic context when
+block.
+This macro may also be used in a non-bibliographic context when
 referring to book titles.
 .Ss \&%C
 Publication city or location of an
@@ -899,8 +907,8 @@ this macro is not implemented in
 .Ss \&%D
 Publication date of an
 .Sx \&Rs
-block.  This should follow the reduced or canonical form syntax
-described in
+block.
+This should follow the reduced or canonical form syntax described in
 .Sx Dates .
 .Ss \&%I
 Publisher or issuer name of an
@@ -925,7 +933,8 @@ block.
 .Ss \&%Q
 Institutional author (school, government, etc.) of an
 .Sx \&Rs
-block.  Multiple institutional authors should each be accorded their own
+block.
+Multiple institutional authors should each be accorded their own
 .Sx \&%Q
 line.
 .Ss \&%R
@@ -935,8 +944,9 @@ block.
 .Ss \&%T
 Article title of an
 .Sx \&Rs
-block.  This macro may also be used in a non-bibliographical context
-when referring to article titles.
+block.
+This macro may also be used in a non-bibliographical context when
+referring to article titles.
 .Ss \&%U
 URI of reference document.
 .Ss \&%V
@@ -946,7 +956,8 @@ block.
 .Ss \&Ac
 Closes an
 .Sx \&Ao
-block.  Does not have any tail arguments.
+block.
+Does not have any tail arguments.
 .Ss \&Ad
 Address construct: usually in the context of an computational address in
 memory, not a physical (post) address.
@@ -958,7 +969,8 @@ Examples:
 Author name.
 This macro may alternatively accepts the following arguments, although
 these may not be specified along with a parameter:
-.Bl -tag -width 12n -offset indent
+.Pp
+.Bl -tag -width "-nosplitX" -offset indent -compact
 .It Fl split
 Renders a line break before each author listing.
 .It Fl nosplit
@@ -966,13 +978,17 @@ The opposite of
 .Fl split .
 .El
 .Pp
-In the AUTHORS section, the default is not to split the first author
+In the
+.Em AUTHORS
+section, the default is not to split the first author
 listing, but all subsequent author listings, whether or not they're
 interspersed by other macros or text, are split.
 Thus, specifying
 .Fl split
 will cause the first listing also to be split.
-If not in the AUTHORS section, the default is not to split.
+If not in the
+.Em AUTHORS
+section, the default is not to split.
 .Pp
 Examples:
 .D1 \&.An -nosplit
@@ -983,9 +999,12 @@ the effects of
 .Fl split
 or
 .Fl nosplit
-are re-set when entering the AUTHORS section, so if one specifies
+are re-set when entering the
+.Em AUTHORS
+section, so if one specifies
 .Sx \&An Fl nosplit
-in the general document body, it must be re-specified in the AUTHORS
+in the general document body, it must be re-specified in the
+.Em AUTHORS
 section.
 .Ss \&Ao
 Begins a block enclosed by angled brackets.
@@ -997,12 +1016,12 @@ Examples:
 See also
 .Sx \&Aq .
 .Ss \&Ap
-Inserts an apostrophe without any surrounding white-space.
+Inserts an apostrophe without any surrounding whitespace.
 This is generally used as a grammatical device when referring to the verb
-form of a function:
-.Bd -literal -offset indent
-\&.Fn execve Ap d
-.Ed
+form of a function.
+.Pp
+Examples:
+.D1 \&.Fn execve \&Ap d
 .Ss \&Aq
 Encloses its arguments in angled brackets.
 .Pp
@@ -1034,7 +1053,8 @@ Examples:
 .Ss \&At
 Formats an AT&T version.
 Accepts at most one parameter:
-.Bl -tag -width 12n -offset indent
+.Pp
+.Bl -tag -width "v[1-7] | 32vX" -offset indent -compact
 .It Cm v[1-7] | 32v
 A version of
 .At .
@@ -1061,7 +1081,8 @@ and
 .Ss \&Bc
 Closes a
 .Sx \&Bo
-block.  Does not have any tail arguments.
+block.
+Does not have any tail arguments.
 .Ss \&Bd
 Begins a display block.
 Its syntax is as follows:
@@ -1310,8 +1331,8 @@ The
 .Fl width
 argument is ignored.
 .It Fl tag
-A list offset by list entry heads.  List entry bodies are positioned
-after the head as specified by the
+A list offset by list entry heads.
+List entry bodies are positioned after the head as specified by the
 .Fl width
 argument.
 .El
@@ -1323,7 +1344,7 @@ Begins a block enclosed by square brackets.
 Does not have any head arguments.
 .Pp
 Examples:
-.Bd -literal -offset indent
+.Bd -literal -offset indent -compact
 \&.Bo 1 ,
 \&.Dv BUFSIZ \&Bc
 .Ed
@@ -1349,13 +1370,14 @@ See also
 .Ss \&Brc
 Closes a
 .Sx \&Bro
-block.  Does not have any tail arguments.
+block.
+Does not have any tail arguments.
 .Ss \&Bro
 Begins a block enclosed by curly braces.
 Does not have any head arguments.
 .Pp
 Examples:
-.Bd -literal -offset indent
+.Bd -literal -offset indent -compact
 \&.Bro 1 , ... ,
 \&.Va n \&Brc
 .Ed
@@ -1417,7 +1439,7 @@ Examples:
 .Pp
 .Em Remarks :
 this macro is commonly abused by using quoted literals to retain
-white-space and align consecutive
+whitespace and align consecutive
 .Sx \&Cd
 declarations.
 This practise is discouraged.
@@ -1453,7 +1475,8 @@ Its syntax is as follows:
 .Ss \&Dc
 Closes a
 .Sx \&Do
-block.  Does not have any tail arguments.
+block.
+Does not have any tail arguments.
 .Ss \&Dd
 Document date.
 This is the mandatory first macro of any
@@ -1489,23 +1512,30 @@ invocations.
 It is followed by a newline.
 .Pp
 Examples:
-.D1 \&.Dl % mandoc mdoc.7 | less
+.D1 \&.Dl % mandoc mdoc.7 \e(ba less
 .Pp
 See also
 .Sx \&Bd
 and
 .Sx \&D1 .
 .Ss \&Do
-Begins a block enclosed by double quotes.  Does not have any head
-arguments.
+Begins a block enclosed by double quotes.
+Does not have any head arguments.
 .Pp
 Examples:
-.D1 \&.D1 \&Do April is the cruellest month \&Dc \e(em T.S. Eliot
+.Bd -literal -offset indent -compact
+\&.Do
+April is the cruellest month
+\&.Dc
+\e(em T.S. Eliot
+.Ed
 .Pp
 See also
 .Sx \&Dq .
 .Ss \&Dq
-Encloses its arguments in double quotes.
+Encloses its arguments in
+.Dq typographic
+double-quotes.
 .Pp
 Examples:
 .Bd -literal -offset indent -compact
@@ -1514,6 +1544,9 @@ Examples:
 .Ed
 .Pp
 See also
+.Sx \&Qq ,
+.Sx \&Sq ,
+and
 .Sx \&Do .
 .Ss \&Dt
 Document title.
@@ -1536,7 +1569,7 @@ Its arguments are as follows:
 .Bl -tag -width Ds -offset Ds
 .It Cm title
 The document's title (name), defaulting to
-.Qq UNKNOWN
+.Dq UNKNOWN
 if unspecified.
 It should be capitalised.
 .It Cm section
@@ -1576,7 +1609,7 @@ or
 .Ar paper
 .Pq paper .
 It should correspond to the manual's filename suffix and defaults to
-.Qq 1
+.Dq 1
 if unspecified.
 .It Cm volume
 This overrides the volume inferred from
@@ -1717,6 +1750,12 @@ stylistically decorating technical terms.
 Examples:
 .D1 \&.Em Warnings!
 .D1 \&.Em Remarks :
+.Pp
+See also
+.Sx \&Bf ,
+.Sx \&Sy ,
+and
+.Sx \&Li .
 .Ss \&En
 This macro is obsolete and not implemented.
 .Ss \&Eo
@@ -1749,16 +1788,19 @@ Examples:
 .D1 \&.Ev DISPLAY
 .D1 \&.Ev PATH
 .Ss \&Ex
-Inserts text regarding a utility's exit values.
-This macro must have first the
+Inserts text regarding a utility's exit value.
+This macro must consist of the
 .Fl std
-argument specified, then an optional
+argument followed by an optional
 .Ar utility .
 If
 .Ar utility
 is not provided, the document's name as stipulated in
 .Sx \&Nm
 is provided.
+.Pp
+See also
+.Sx \&Rv .
 .Ss \&Fa
 Function argument.
 Its syntax is as follows:
@@ -1878,6 +1920,7 @@ See also
 .Sx \&Fa ,
 .Sx \&Fc ,
 and
+.Sx \&Ft .
 .Ss \&Ft
 A function type.
 Its syntax is as follows:
@@ -1934,13 +1977,13 @@ is preferred for displaying code; the
 macro is used when referring to specific instructions.
 .Ss \&In
 An
-.Qq include
+.Dq include
 file.
 In the
 .Em SYNOPSIS
 section (only if invoked as the line macro), the first argument is
 preceded by
-.Qq #include ,
+.Dq #include ,
 the arguments is enclosed in angled braces.
 .Pp
 Examples:
@@ -2012,8 +2055,8 @@ are interpreted within the scope of the last phrase.
 Calling the pseudo-macro
 .Sq \&Ta
 will open a new phrase scope (this must occur on a macro line to be
-interpreted as a macro).  Note that the tab phrase delimiter may only be
-used within the
+interpreted as a macro).
+Note that the tab phrase delimiter may only be used within the
 .Sx \&It
 line itself.
 Subsequent this, only the
@@ -2057,6 +2100,12 @@ Examples:
 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.
+.Pp
+See also
+.Sx \&Bf ,
+.Sx \&Sy ,
+and
+.Sx \&Em .
 .Ss \&Lk
 Format a hyperlink.
 Its syntax is as follows:
@@ -2073,9 +2122,17 @@ See also
 Synonym for
 .Sx \&Pp .
 .Ss \&Ms
+Display a mathematical symbol.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&Ms Cm symbol
+.Pp
+Examples:
+.D1 \&.Ms sigma
+.D1 \&.Ms aleph
 .Ss \&Mt
 Format a
-.Qq mailto:
+.Dq mailto:
 hyperlink.
 Its syntax is as follows:
 .Pp
@@ -2146,12 +2203,23 @@ macro rather than
 to mark up the name of the manual page.
 .Ss \&No
 A
-.Qq noop
+.Dq noop
 macro used to terminate prior macro contexts.
 .Pp
 Examples:
 .D1 \&.Sx \&Fl ab \&No cd \&Fl ef
 .Ss \&Ns
+Suppress a space.
+Following invocation, text is interpreted as free-form text until a
+macro is encountered.
+.Pp
+Examples:
+.D1 \&.Fl o \&Ns \&Ar output
+.Pp
+See also
+.Sx \&No
+and
+.Sx \&Sm .
 .Ss \&Nx
 Format the NetBSD version provided as an argument, or a default value if
 no argument is provided.
@@ -2178,7 +2246,7 @@ Multi-line version of
 .Sx \&Op .
 .Pp
 Examples:
-.Bd -literal -offset indent
+.Bd -literal -offset indent -compact
 \&.Oo
 \&.Op Fl flag Ns Ar value
 \&.Oc
@@ -2255,7 +2323,7 @@ Close parenthesised context opened by
 .Sx \&Po .
 .Ss \&Pf
 Removes the space
-.Pq Qq prefix
+.Pq Dq prefix
 between its arguments.
 Its syntax is as follows:
 .Pp
@@ -2280,9 +2348,29 @@ Parenthesised enclosure.
 See also
 .Sx \&Po .
 .Ss \&Qc
+Close quoted context opened by
+.Sx \&Qo .
 .Ss \&Ql
+Format a single-quoted literal.
+See also
+.Sx \&Qq
+and
+.Sx \&Sq .
 .Ss \&Qo
+Multi-line version of
+.Sx \&Qq .
 .Ss \&Qq
+Encloses its arguments in
+.Dq typewriter
+double-quotes.
+Consider using
+.Sx \&Dq .
+.Pp
+See also
+.Sx \&Dq ,
+.Sx \&Sq ,
+and
+.Sx \&Qo .
 .Ss \&Re
 Closes a
 .Sx \&Rs
@@ -2329,8 +2417,37 @@ block is used within a SEE ALSO section, a vertical space is asserted
 before the rendered output, else the block continues on the current
 line.
 .Ss \&Rv
+Inserts text regarding a function call's return value.
+This macro must consist of the
+.Fl std
+argument followed by an optional
+.Ar function .
+If
+.Ar function
+is not provided, the document's name as stipulated by the first
+.Sx \&Nm
+is provided.
+.Pp
+See also
+.Sx \&Ex .
 .Ss \&Sc
+Close single-quoted context opened by
+.Sx \&So .
 .Ss \&Sh
+Begin a new section.
+For a list of conventional manual sections, see
+.Sx MANUAL STRUCTURE .
+These sections should be used unless it's absolutely necessary that
+custom sections be used.
+.Pp
+Section names should be unique so that they may be keyed by
+.Sx \&Sx .
+.Pp
+See also
+.Sx \&Pp ,
+.Sx \&Ss ,
+and
+.Sx \&Sx .
 .Ss \&Sm
 Switches the spacing mode for output generated from macros.
 Its syntax is as follows:
@@ -2345,12 +2462,155 @@ no white space is inserted between macro arguments and between the
 output generated from adjacent macros, but free-form text lines
 still get normal spacing between words and sentences.
 .Ss \&So
+Multi-line version of
+.Sx \&Sq .
 .Ss \&Sq
+Encloses its arguments in
+.Dq typewriter
+single-quotes.
+.Pp
+See also
+.Sx \&Dq ,
+.Sx \&Qq ,
+and
+.Sx \&So .
 .Ss \&Ss
+Begin a new sub-section.
+Unlike with
+.Sx \&Sh ,
+there's no convention for sub-sections.
+Conventional sections, as described in
+.Sx MANUAL STRUCTURE ,
+rarely have sub-sections.
+.Pp
+Sub-section names should be unique so that they may be keyed by
+.Sx \&Sx .
+.Pp
+See also
+.Sx \&Pp ,
+.Sx \&Sh ,
+and
+.Sx \&Sx .
 .Ss \&St
+Replace an abbreviation for a standard with the full form.
+The following standards are recognised:
+.Pp
+.Bl -tag -width "-p1003.1g-2000X" -compact
+.It \-p1003.1-88
+.St -p1003.1-88
+.It \-p1003.1-90
+.St -p1003.1-90
+.It \-p1003.1-96
+.St -p1003.1-96
+.It \-p1003.1-2001
+.St -p1003.1-2001
+.It \-p1003.1-2004
+.St -p1003.1-2004
+.It \-p1003.1-2008
+.St -p1003.1-2008
+.It \-p1003.1
+.St -p1003.1
+.It \-p1003.1b
+.St -p1003.1b
+.It \-p1003.1b-93
+.St -p1003.1b-93
+.It \-p1003.1c-95
+.St -p1003.1c-95
+.It \-p1003.1g-2000
+.St -p1003.1g-2000
+.It \-p1003.1i-95
+.St -p1003.1i-95
+.It \-p1003.2-92
+.St -p1003.2-92
+.It \-p1003.2a-92
+.St -p1003.2a-92
+.It \-p1387.2-95
+.St -p1387.2-95
+.It \-p1003.2
+.St -p1003.2
+.It \-p1387.2
+.St -p1387.2
+.It \-isoC
+.St -isoC
+.It \-isoC-90
+.St -isoC-90
+.It \-isoC-amd1
+.St -isoC-amd1
+.It \-isoC-tcor1
+.St -isoC-tcor1
+.It \-isoC-tcor2
+.St -isoC-tcor2
+.It \-isoC-99
+.St -isoC-99
+.It \-iso9945-1-90
+.St -iso9945-1-90
+.It \-iso9945-1-96
+.St -iso9945-1-96
+.It \-iso9945-2-93
+.St -iso9945-2-93
+.It \-ansiC
+.St -ansiC
+.It \-ansiC-89
+.St -ansiC-89
+.It \-ansiC-99
+.St -ansiC-99
+.It \-ieee754
+.St -ieee754
+.It \-iso8802-3
+.St -iso8802-3
+.It \-ieee1275-94
+.St -ieee1275-94
+.It \-xpg3
+.St -xpg3
+.It \-xpg4
+.St -xpg4
+.It \-xpg4.2
+.St -xpg4.2
+.St -xpg4.3
+.It \-xbd5
+.St -xbd5
+.It \-xcu5
+.St -xcu5
+.It \-xsh5
+.St -xsh5
+.It \-xns5
+.St -xns5
+.It \-xns5.2
+.St -xns5.2
+.It \-xns5.2d2.0
+.St -xns5.2d2.0
+.It \-xcurses4.2
+.St -xcurses4.2
+.It \-susv2
+.St -susv2
+.It \-susv3
+.St -susv3
+.It \-svid4
+.St -svid4
+.El
 .Ss \&Sx
+Reference a section or sub-section.
+The referenced section or sub-section name must be identical to the
+enclosed argument, including whitespace.
+.Pp
+Examples:
+.D1 \&.Sx MANUAL STRUCTURE
 .Ss \&Sy
+Format enclosed arguments in symbolic
+.Pq Dq boldface .
+Note that this is a presentation term and should not be used for
+stylistically decorating technical terms.
+.Pp
+See also
+.Sx \&Bf ,
+.Sx \&Li ,
+and
+.Sx \&Em .
 .Ss \&Tn
+Format a tradename.
+.Pp
+Examples:
+.D1 \&.Tn IBM
 .Ss \&Ud
 Prints out
 .Dq currently under development.
@@ -2433,7 +2693,28 @@ Examples:
 .D1 \&.Xr mandoc 1 \&;
 .D1 \&.Xr mandoc 1 \&Ns s behaviour
 .Ss \&br
+Emits a line-break.
+This macro should not be used; it is implemented for compatibility with
+historical manuals.
+.Pp
+Consider using
+.Sx \&Pp
+in the event of natural paragraph breaks.
 .Ss \&sp
+Emits vertical space.
+This macro should not be used; it is implemented for compatibility with
+historical manuals.
+Its syntax is as follows:
+.Pp
+.D1 Pf \. Sx \&sp Op Cm height
+.Pp
+The
+.Cm height
+argument must be formatted as described in
+.Sx Scaling Widths .
+If unspecified,
+.Sx \&sp
+asserts a single vertical space.
 .Sh COMPATIBILITY
 This section documents compatibility between mandoc and other other
 troff implementations, at this time limited to GNU troff
@@ -2589,71 +2870,3 @@ The
 .Nm
 reference was written by
 .An Kristaps Dzonsons Aq kristaps@bsd.lv .
-.\"
-.\" XXX: this really isn't the place for these caveats.
-.\" .
-.\" .
-.\" .Sh CAVEATS
-.\" There are many ambiguous parts of mdoc.
-.\" .
-.\" .Pp
-.\" .Bl -dash -compact
-.\" .It
-.\" .Sq \&Fa
-.\" should be
-.\" .Sq \&Va
-.\" as function arguments are variables.
-.\" .It
-.\" .Sq \&Ft
-.\" should be
-.\" .Sq \&Vt
-.\" as function return types are still types.  Furthermore, the
-.\" .Sq \&Ft
-.\" should be removed and
-.\" .Sq \&Fo ,
-.\" which ostensibly follows it, should follow the same convention as
-.\" .Sq \&Va .
-.\" .It
-.\" .Sq \&Va
-.\" should formalise that only one or two arguments are acceptable: a
-.\" variable name and optional, preceding type.
-.\" .It
-.\" .Sq \&Fd
-.\" is ambiguous.  It's commonly used to indicate an include file in the
-.\" synopsis section.
-.\" .Sq \&In
-.\" should be used, instead.
-.\" .It
-.\" Only the
-.\" .Sq \-literal
-.\" argument to
-.\" .Sq \&Bd
-.\" makes sense.  The remaining ones should be removed.
-.\" .It
-.\" The
-.\" .Sq \&Xo
-.\" and
-.\" .Sq \&Xc
-.\" macros should be deprecated.
-.\" .It
-.\" The
-.\" .Sq \&Dt
-.\" macro lacks clarity.  It should be absolutely clear which title will
-.\" render when formatting the manual page.
-.\" .It
-.\" A
-.\" .Sq \&Lx
-.\" should be provided for Linux (\(`a la
-.\" .Sq \&Ox ,
-.\" .Sq \&Nx
-.\" etc.).
-.\" .It
-.\" There's no way to refer to references in
-.\" .Sq \&Rs/Re
-.\" blocks.
-.\" .It
-.\" The \-split and \-nosplit dictates via
-.\" .Sq \&An
-.\" are re-set when entering and leaving the AUTHORS section.
-.\" .El
-.\" .
index 738db79..7868408 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc.h,v 1.31 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: mdoc.h,v 1.32 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -155,35 +155,36 @@ enum      mdoct {
 
 /* What follows is a list of ALL possible macro arguments. */
 
-/* FIXME: make this into an enum. */
-#define        MDOC_Split       0
-#define        MDOC_Nosplit     1
-#define        MDOC_Ragged      2
-#define        MDOC_Unfilled    3
-#define        MDOC_Literal     4
-#define        MDOC_File        5
-#define        MDOC_Offset      6
-#define        MDOC_Bullet      7
-#define        MDOC_Dash        8
-#define        MDOC_Hyphen      9
-#define        MDOC_Item        10
-#define        MDOC_Enum        11
-#define        MDOC_Tag         12
-#define        MDOC_Diag        13
-#define        MDOC_Hang        14
-#define        MDOC_Ohang       15
-#define        MDOC_Inset       16
-#define        MDOC_Column      17
-#define        MDOC_Width       18
-#define        MDOC_Compact     19
-#define        MDOC_Std         20
-#define        MDOC_Filled      21
-#define        MDOC_Words       22
-#define        MDOC_Emphasis    23
-#define        MDOC_Symbolic    24
-#define        MDOC_Nested      25
-#define        MDOC_Centred     26
-#define        MDOC_ARG_MAX     27
+enum   mdocargt {
+       MDOC_Split,
+       MDOC_Nosplit,
+       MDOC_Ragged,
+       MDOC_Unfilled,
+       MDOC_Literal,
+       MDOC_File,
+       MDOC_Offset,
+       MDOC_Bullet,
+       MDOC_Dash,
+       MDOC_Hyphen,
+       MDOC_Item,
+       MDOC_Enum,
+       MDOC_Tag,
+       MDOC_Diag,
+       MDOC_Hang,
+       MDOC_Ohang,
+       MDOC_Inset,
+       MDOC_Column,
+       MDOC_Width,
+       MDOC_Compact,
+       MDOC_Std,
+       MDOC_Filled,
+       MDOC_Words,
+       MDOC_Emphasis,
+       MDOC_Symbolic,
+       MDOC_Nested,
+       MDOC_Centred,
+       MDOC_ARG_MAX
+};
 
 /* Type of a syntax node. */
 enum   mdoc_type {
@@ -236,7 +237,7 @@ struct      mdoc_meta {
 
 /* An argument to a macro (multiple values = `It -column'). */
 struct mdoc_argv {
-       int               arg;
+       enum mdocargt     arg;
        int               line;
        int               pos;
        size_t            sz;
index 61d5dbb..166ced6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_argv.c,v 1.32 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: mdoc_argv.c,v 1.33 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -41,7 +41,7 @@
 
 #define        MULTI_STEP       5
 
-static int              argv_a2arg(enum mdoct, const char *);
+static enum mdocargt    argv_a2arg(enum mdoct, const char *);
 static enum margserr    args(struct mdoc *, int, int *, 
                                char *, int, char **);
 static int              argv(struct mdoc *, int, 
@@ -309,9 +309,11 @@ mdoc_argv_free(struct mdoc_arg *p)
 void
 mdoc_argn_free(struct mdoc_arg *p, int iarg)
 {
-       struct mdoc_argv *arg = &p->argv[iarg];
+       struct mdoc_argv *arg;
        int               j;
 
+       arg = &p->argv[iarg];
+
        if (arg->sz && arg->value) {
                for (j = (int)arg->sz - 1; j >= 0; j--) 
                        free(arg->value[j]);
@@ -579,7 +581,7 @@ args(struct mdoc *m, int line, int *pos,
 }
 
 
-static int
+static enum mdocargt
 argv_a2arg(enum mdoct tok, const char *p)
 {
 
index b088164..73c7aa5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_html.c,v 1.25 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: mdoc_html.c,v 1.26 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -121,6 +121,7 @@ static      int               mdoc_pq_pre(MDOC_ARGS);
 static int               mdoc_rs_pre(MDOC_ARGS);
 static int               mdoc_rv_pre(MDOC_ARGS);
 static int               mdoc_sh_pre(MDOC_ARGS);
+static int               mdoc_sm_pre(MDOC_ARGS);
 static int               mdoc_sp_pre(MDOC_ARGS);
 static void              mdoc_sq_post(MDOC_ARGS);
 static int               mdoc_sq_pre(MDOC_ARGS);
@@ -205,7 +206,7 @@ static      const struct htmlmdoc mdocs[MDOC_MAX] = {
        {mdoc_em_pre, NULL}, /* Em */ 
        {NULL, NULL}, /* Eo */
        {mdoc_xx_pre, NULL}, /* Fx */
-       {mdoc_ms_pre, NULL}, /* Ms */ /* FIXME: convert to symbol? */
+       {mdoc_ms_pre, NULL}, /* Ms */
        {NULL, NULL}, /* No */
        {mdoc_ns_pre, NULL}, /* Ns */
        {mdoc_xx_pre, NULL}, /* Nx */
@@ -223,7 +224,7 @@ static      const struct htmlmdoc mdocs[MDOC_MAX] = {
        {NULL, NULL}, /* Sc */
        {mdoc_sq_pre, mdoc_sq_post}, /* So */
        {mdoc_sq_pre, mdoc_sq_post}, /* Sq */
-       {NULL, NULL}, /* Sm */ /* FIXME - no idea. */
+       {mdoc_sm_pre, NULL}, /* Sm */ 
        {mdoc_sx_pre, NULL}, /* Sx */
        {mdoc_sy_pre, NULL}, /* Sy */
        {NULL, NULL}, /* Tn */
@@ -1716,6 +1717,23 @@ mdoc_fn_pre(MDOC_ARGS)
 }
 
 
+/* ARGSUSED */
+static int
+mdoc_sm_pre(MDOC_ARGS)
+{
+
+       assert(n->child && MDOC_TEXT == n->child->type);
+       if (0 == strcmp("on", n->child->string)) {
+               /* FIXME: no p->col to check... */
+               h->flags &= ~HTML_NOSPACE;
+               h->flags &= ~HTML_NONOSPACE;
+       } else
+               h->flags |= HTML_NONOSPACE;
+
+       return(0);
+}
+
+
 /* ARGSUSED */
 static int
 mdoc_sp_pre(MDOC_ARGS)
@@ -1733,6 +1751,11 @@ mdoc_sp_pre(MDOC_ARGS)
                len = 0;
                break;
        default:
+               assert(n->parent);
+               if ((NULL == n->next || NULL == n->prev) &&
+                               (MDOC_Ss == n->parent->tok ||
+                                MDOC_Sh == n->parent->tok))
+                       return(0);
                len = 1;
                break;
        }
index 629dcdb..0dce300 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_term.c,v 1.97 2010/07/21 21:44:28 schwarze Exp $ */
+/*     $Id: mdoc_term.c,v 1.98 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -204,7 +204,7 @@ static      const struct termact termacts[MDOC_MAX] = {
        { termp_under_pre, NULL }, /* Em */ 
        { NULL, NULL }, /* Eo */
        { termp_xx_pre, NULL }, /* Fx */
-       { termp_bold_pre, NULL }, /* Ms */ /* FIXME: convert to symbol? */
+       { termp_bold_pre, NULL }, /* Ms */
        { NULL, NULL }, /* No */
        { termp_ns_pre, NULL }, /* Ns */
        { termp_xx_pre, NULL }, /* Nx */
@@ -1902,6 +1902,11 @@ termp_sp_pre(DECL_ARGS)
                len = 0;
                break;
        default:
+               assert(n->parent);
+               if ((NULL == n->next || NULL == n->prev) &&
+                               (MDOC_Ss == n->parent->tok ||
+                                MDOC_Sh == n->parent->tok))
+                       return(0);
                len = 1;
                break;
        }
index 2b1fc08..9cffeaa 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: mdoc_validate.c,v 1.65 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: mdoc_validate.c,v 1.66 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -28,7 +28,6 @@
 #include "libmandoc.h"
 
 /* FIXME: .Bl -diag can't have non-text children in HEAD. */
-/* TODO: ignoring Pp (it's superfluous in some invocations). */
 
 #define        PRE_ARGS  struct mdoc *mdoc, struct mdoc_node *n
 #define        POST_ARGS struct mdoc *mdoc
@@ -450,26 +449,29 @@ check_argv(struct mdoc *m, struct mdoc_node *n, struct mdoc_argv *v)
 
 
 static int
-check_text(struct mdoc *mdoc, int line, int pos, char *p)
+check_text(struct mdoc *m, int ln, int pos, char *p)
 {
        int              c;
-
-       /* 
-        * FIXME: we absolutely cannot let \b get through or it will
-        * destroy some assumptions in terms of format.
-        */
+       size_t           sz;
 
        for ( ; *p; p++, pos++) {
+               sz = strcspn(p, "\t\\");
+               p += (int)sz;
+
+               if ('\0' == *p)
+                       break;
+
+               pos += (int)sz;
+
                if ('\t' == *p) {
-                       if ( ! (MDOC_LITERAL & mdoc->flags))
-                               if ( ! mdoc_pmsg(mdoc, line, pos, MANDOCERR_BADCHAR))
-                                       return(0);
-               } else if ( ! isprint((u_char)*p) && ASCII_HYPH != *p)
-                       if ( ! mdoc_pmsg(mdoc, line, pos, MANDOCERR_BADCHAR))
-                               return(0);
+                       if (MDOC_LITERAL & m->flags)
+                               continue;
+                       if (mdoc_pmsg(m, ln, pos, MANDOCERR_BADTAB))
+                               continue;
+                       return(0);
+               }
 
-               if ('\\' != *p)
-                       continue;
+               /* Check the special character. */
 
                c = mandoc_special(p);
                if (c) {
@@ -478,8 +480,8 @@ check_text(struct mdoc *mdoc, int line, int pos, char *p)
                        continue;
                }
 
-               c = mdoc_pmsg(mdoc, line, pos, MANDOCERR_BADESCAPE);
-               if ( ! (MDOC_IGN_ESCAPE & mdoc->pflags) && ! c)
+               c = mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE);
+               if ( ! (MDOC_IGN_ESCAPE & m->pflags) && ! c)
                        return(c);
        }
 
@@ -487,8 +489,6 @@ check_text(struct mdoc *mdoc, int line, int pos, char *p)
 }
 
 
-
-
 static int
 check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
 {
@@ -506,7 +506,6 @@ check_parent(PRE_ARGS, enum mdoct tok, enum mdoc_type t)
 }
 
 
-
 static int
 pre_display(PRE_ARGS)
 {
@@ -621,6 +620,8 @@ pre_bl(PRE_ARGS)
                        if ( ! mdoc_nmsg(mdoc, n, MANDOCERR_IGNARGV))
                                return(0);
                        break;
+               default:
+                       continue;
                }
 
                /* Check: duplicate auxiliary arguments. */
@@ -943,7 +944,7 @@ static int
 post_bf(POST_ARGS)
 {
        struct mdoc_node *np;
-       int               arg;
+       enum mdocargt     arg;
 
        /*
         * Unlike other data pointers, these are "housed" by the HEAD
index f79643f..bbde1ea 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: out.c,v 1.5 2010/06/27 20:28:56 schwarze Exp $ */
+/*     $Id: out.c,v 1.6 2010/07/25 18:05:54 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * 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
 
 #include "out.h"
 
-/* See a2roffdeco(). */
-#define        C2LIM(c, l) do { \
-       (l) = 1; \
-       if ('[' == (c) || '\'' == (c)) \
-               (l) = 0; \
-       else if ('(' == (c)) \
-               (l) = 2; } \
-       while (/* CONSTCOND */ 0)
-
-/* See a2roffdeco(). */
-#define        C2TERM(c, t) do { \
-       (t) = 0; \
-       if ('\'' == (c)) \
-               (t) = 1; \
-       else if ('[' == (c)) \
-               (t) = 2; \
-       else if ('(' == (c)) \
-               (t) = 3; } \
-       while (/* CONSTCOND */ 0)
-
 /* 
  * Convert a `scaling unit' to a consistent form, or fail.  Scaling
  * units are documented in groff.7, mdoc.7, man.7.
@@ -132,6 +112,7 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def)
                return(0);
        }
 
+       /* FIXME: do this in the caller. */
        if ((dst->scale = atof(buf)) < 0)
                dst->scale = 0;
        dst->unit = unit;
@@ -181,213 +162,153 @@ time2a(time_t t, char *dst, size_t sz)
 }
 
 
-/* 
- * Returns length of parsed string (the leading "\" should NOT be
- * included).  This can be zero if the current character is the nil
- * terminator.  "d" is set to the type of parsed decorator, which may
- * have an adjoining "word" of size "sz" (e.g., "(ab" -> "ab", 2).
- */
 int
-a2roffdeco(enum roffdeco *d,
-               const char **word, size_t *sz)
+a2roffdeco(enum roffdeco *d, const char **word, size_t *sz)
 {
-       int              j, term, lim;
-       char             set;
-       const char      *wp, *sp;
+       int              i, j, lim;
+       char             term, c;
+       const char      *wp;
 
        *d = DECO_NONE;
+       lim = i = 0;
+       term = '\0';
        wp = *word;
 
-       switch ((set = *wp)) {
-       case ('\0'):
-               return(0);
-
+       switch ((c = wp[i++])) {
        case ('('):
-               if ('\0' == *(++wp))
-                       return(1);
-               if ('\0' == *(wp + 1))
-                       return(2);
-
                *d = DECO_SPECIAL;
-               *sz = 2;
-               *word = wp;
-               return(3);
-
+               lim = 2;
+               break;
        case ('F'):
                /* FALLTHROUGH */
        case ('f'):
-               /*
-                * FIXME: this needs work and consolidation (it should
-                * follow the sequence that special characters do, for
-                * one), but isn't a priority at the moment.  Note, for
-                * one, that in reality \fB != \FB, although here we let
-                * these slip by.
-                */
-               switch (*(++wp)) {
-               case ('\0'):
-                       return(1);
+               *d = 'F' == c ? DECO_FFONT : DECO_FONT;
+
+               switch (wp[i++]) {
+               case ('('):
+                       lim = 2;
+                       break;
+               case ('['):
+                       term = ']';
+                       break;
                case ('3'):
                        /* FALLTHROUGH */
                case ('B'):
                        *d = DECO_BOLD;
-                       return(2);
+                       return(i);
                case ('2'):
                        /* FALLTHROUGH */
                case ('I'):
                        *d = DECO_ITALIC;
-                       return(2);
+                       return(i);
                case ('P'):
                        *d = DECO_PREVIOUS;
-                       return(2);
+                       return(i);
                case ('1'):
                        /* FALLTHROUGH */
                case ('R'):
                        *d = DECO_ROMAN;
-                       return(2);
-               case ('('):
-                       if ('\0' == *(++wp))
-                               return(2);
-                       if ('\0' == *(wp + 1))
-                               return(3);
-
-                       *d = 'F' == set ? DECO_FFONT : DECO_FONT;
-                       *sz = 2;
-                       *word = wp;
-                       return(4);
-               case ('['):
-                       *word = ++wp;
-                       for (j = 0; *wp && ']' != *wp; wp++, j++)
-                               /* Loop... */ ;
-
-                       if ('\0' == *wp)
-                               return(j + 2);
-
-                       *d = 'F' == set ? DECO_FFONT : DECO_FONT;
-                       *sz = (size_t)j;
-                       return(j + 3);
+                       return(i);
                default:
+                       i--;
+                       lim = 1;
                        break;
                }
-
-               *d = 'F' == set ? DECO_FFONT : DECO_FONT;
-               *sz = 1;
-               *word = wp;
-               return(2);
-
+               break;
+       case ('M'):
+               /* FALLTHROUGH */
+       case ('m'):
+               /* FALLTHROUGH */
        case ('*'):
-               switch (*(++wp)) {
-               case ('\0'):
-                       return(1);
-
-               case ('('):
-                       if ('\0' == *(++wp))
-                               return(2);
-                       if ('\0' == *(wp + 1))
-                               return(3);
-
+               if ('*' == c)
                        *d = DECO_RESERVED;
-                       *sz = 2;
-                       *word = wp;
-                       return(4);
 
+               switch (wp[i++]) {
+               case ('('):
+                       lim = 2;
+                       break;
                case ('['):
-                       *word = ++wp;
-                       for (j = 0; *wp && ']' != *wp; wp++, j++)
-                               /* Loop... */ ;
-
-                       if ('\0' == *wp)
-                               return(j + 2);
-
-                       *d = DECO_RESERVED;
-                       *sz = (size_t)j;
-                       return(j + 3);
-
+                       term = ']';
+                       break;
                default:
+                       i--;
+                       lim = 1;
                        break;
                }
-
-               *d = DECO_RESERVED;
-               *sz = 1;
-               *word = wp;
-               return(2);
-
+               break;
        case ('s'):
-               sp = wp;
-               if ('\0' == *(++wp))
-                       return(1);
-
-               C2LIM(*wp, lim);
-               C2TERM(*wp, term);
-
-               if (term) 
-                       wp++;
+               if ('+' == wp[i] || '-' == wp[i])
+                       i++;
 
-               *word = wp;
+               j = ('s' != wp[i - 1]);
 
-               if (*wp == '+' || *wp == '-')
-                       ++wp;
-
-               switch (*wp) {
-               case ('\''):
-                       /* FALLTHROUGH */
-               case ('['):
-                       /* FALLTHROUGH */
+               switch (wp[i++]) {
                case ('('):
-                       if (term) 
-                               return((int)(wp - sp));
-
-                       C2LIM(*wp, lim);
-                       C2TERM(*wp, term);
-                       wp++;
+                       lim = 2;
                        break;
+               case ('['):
+                       term = ']';
+                       break;
+               case ('\''):
+                       term = '\'';
+                       break;
+               case ('0'):
+                       j++;
+                       /* FALLTHROUGH */
                default:
+                       i--;
+                       lim = 1;
                        break;
                }
 
-               if ( ! isdigit((u_char)*wp))
-                       return((int)(wp - sp));
-
-               for (j = 0; isdigit((u_char)*wp); j++) {
-                       if (lim && j >= lim)
-                               break;
-                       ++wp;
-               }
-
-               if (term && term < 3) {
-                       if (1 == term && *wp != '\'')
-                               return((int)(wp - sp));
-                       if (2 == term && *wp != ']')
-                               return((int)(wp - sp));
-                       ++wp;
-               }
-
-               *d = DECO_SIZE;
-               return((int)(wp - sp));
-
+               if ('+' == wp[i] || '-' == wp[i]) {
+                       if (j++)
+                               return(i);
+                       i++;
+               } 
+               
+               if (0 == j)
+                       return(i);
+               break;
        case ('['):
-               *word = ++wp;
-
-               for (j = 0; *wp && ']' != *wp; wp++, j++)
-                       /* Loop... */ ;
-
-               if ('\0' == *wp)
-                       return(j + 1);
-
                *d = DECO_SPECIAL;
-               *sz = (size_t)j;
-               return(j + 2);
-
+               term = ']';
+               break;
        case ('c'):
                *d = DECO_NOSPACE;
-               *sz = 1;
-               return(1);
-
+               return(i);
        default:
+               *d = DECO_SSPECIAL;
+               i--;
+               lim = 1;
                break;
        }
 
-       *d = DECO_SPECIAL;
-       *word = wp;
-       *sz = 1;
-       return(1);
+       assert(term || lim);
+       *word = &wp[i];
+
+       if (term) {
+               j = i;
+               while (wp[i] && wp[i] != term)
+                       i++;
+               if ('\0' == wp[i]) {
+                       *d = DECO_NONE;
+                       return(i);
+               }
+
+               assert(i >= j);
+               *sz = (size_t)(i - j);
+
+               return(i + 1);
+       }
+
+       assert(lim > 0);
+       *sz = (size_t)lim;
+
+       for (j = 0; wp[i] && j < lim; j++)
+               i++;
+       if (j < lim)
+               *d = DECO_NONE;
+
+       return(i);
 }
index b32f8c7..bbd24ab 100644 (file)
@@ -1,6 +1,6 @@
-/*     $Id: out.h,v 1.5 2010/06/27 20:28:56 schwarze Exp $ */
+/*     $Id: out.h,v 1.6 2010/07/25 18:05:54 schwarze Exp $ */
 /*
- * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
+ * Copyright (c) 2009 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
@@ -37,13 +37,13 @@ enum        roffscale {
 
 enum   roffdeco {
        DECO_NONE,
-       DECO_SPECIAL,
-       DECO_RESERVED,
+       DECO_SPECIAL, /* special character */
+       DECO_SSPECIAL, /* single-char special */
+       DECO_RESERVED, /* reserved word */
        DECO_BOLD,
        DECO_ITALIC,
        DECO_ROMAN,
        DECO_PREVIOUS,
-       DECO_SIZE,
        DECO_NOSPACE,
        DECO_FONT, /* font */
        DECO_FFONT, /* font family */
index 4522f78..0d9fd8c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: roff.c,v 1.8 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: roff.c,v 1.9 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -124,8 +124,8 @@ 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 int              roff_res(struct roff *, int, 
-                               char **, size_t *, int, int *);
+static int              roff_res(struct roff *, 
+                               char **, size_t *, int);
 static void             roff_setstr(struct roff *,
                                const char *, const char *);
 
@@ -324,14 +324,14 @@ roff_alloc(struct regset *regs, const mandocmsg msg, void *data)
  * is processed. 
  */
 static int
-roff_res(struct roff *r, int ln, char **bufp,
-               size_t *szp, int pos, int *offs)
+roff_res(struct roff *r, char **bufp, size_t *szp, int pos)
 {
        const char      *cp, *cpp, *st, *res;
        int              i, maxl;
        size_t           nsz;
        char            *n;
 
+       /* LINTED */
        for (cp = &(*bufp)[pos]; (cpp = strstr(cp, "\\*")); cp++) {
                cp = cpp + 2;
                switch (*cp) {
@@ -396,7 +396,7 @@ roff_parseln(struct roff *r, int ln, char **bufp,
         * words to fill in.
         */
 
-       if (r->first_string && ! roff_res(r, ln, bufp, szp, pos, offs))
+       if (r->first_string && ! roff_res(r, bufp, szp, pos))
                return(ROFF_RERUN);
 
        /*
index 459c17a..231616c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: term.c,v 1.44 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: term.c,v 1.45 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  * Copyright (c) 2010 Ingo Schwarze <schwarze@openbsd.org>
@@ -30,7 +30,8 @@
 #include "term.h"
 #include "main.h"
 
-static void              spec(struct termp *, const char *, size_t);
+static void              spec(struct termp *, enum roffdeco,
+                               const char *, size_t);
 static void              res(struct termp *, const char *, size_t);
 static void              buffera(struct termp *, const char *, size_t);
 static void              bufferc(struct termp *, char);
@@ -356,14 +357,16 @@ term_vspace(struct termp *p)
 
 
 static void
-spec(struct termp *p, const char *word, size_t len)
+spec(struct termp *p, enum roffdeco d, const char *word, size_t len)
 {
        const char      *rhs;
        size_t           sz;
 
-       rhs = chars_a2ascii(p->symtab, word, len, &sz);
+       rhs = chars_spec2str(p->symtab, word, len, &sz);
        if (rhs) 
                encode(p, rhs, sz);
+       else if (DECO_SSPECIAL == d)
+               encode(p, word, len);
 }
 
 
@@ -373,7 +376,7 @@ res(struct termp *p, const char *word, size_t len)
        const char      *rhs;
        size_t           sz;
 
-       rhs = chars_a2res(p->symtab, word, len, &sz);
+       rhs = chars_res2str(p->symtab, word, len, &sz);
        if (rhs)
                encode(p, rhs, sz);
 }
@@ -499,14 +502,13 @@ term_word(struct termp *p, const char *word)
 
        p->flags &= ~TERMP_SENTENCE;
 
-       /* FIXME: use strcspn. */
-
        while (*word) {
-               if ('\\' != *word) {
-                       encode(p, word, 1);
-                       word++;
+               if ((ssz = strcspn(word, "\\")) > 0)
+                       encode(p, word, ssz);
+
+               word += ssz;
+               if ('\\' != *word)
                        continue;
-               }
 
                seq = ++word;
                sz = a2roffdeco(&deco, &seq, &ssz);
@@ -516,7 +518,9 @@ term_word(struct termp *p, const char *word)
                        res(p, seq, ssz);
                        break;
                case (DECO_SPECIAL):
-                       spec(p, seq, ssz);
+                       /* FALLTHROUGH */
+               case (DECO_SSPECIAL):
+                       spec(p, deco, seq, ssz);
                        break;
                case (DECO_BOLD):
                        term_fontrepl(p, TERMFONT_BOLD);
@@ -543,7 +547,7 @@ term_word(struct termp *p, const char *word)
         * Note that we don't process the pipe: the parser sees it as
         * punctuation, but we don't in terms of typography.
         */
-       if (sv[0] && 0 == sv[1])
+       if (sv[0] && '\0' == sv[1])
                switch (sv[0]) {
                case('('):
                        /* FALLTHROUGH */
index ff2585a..fd67cd9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: term.h,v 1.25 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: term.h,v 1.26 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
@@ -27,7 +27,8 @@ enum  termenc {
 
 enum   termtype {
        TERMTYPE_CHAR,
-       TERMTYPE_PS
+       TERMTYPE_PS,
+       TERMTYPE_PDF
 };
 
 enum   termfont {
@@ -63,6 +64,9 @@ struct        termp_ps {
        size_t            left;         /* body left (AFM units) */
        size_t            header;       /* header pos (AFM units) */
        size_t            footer;       /* footer pos (AFM units) */
+       size_t            pdfbytes;
+       size_t            pdflastpg;
+       size_t            pdfbody;
 };
 
 struct termp {
index 44fa34e..5d570c6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $Id: term_ps.c,v 1.6 2010/07/13 01:09:13 schwarze Exp $ */
+/*     $Id: term_ps.c,v 1.7 2010/07/25 18:05:54 schwarze Exp $ */
 /*
  * Copyright (c) 2010 Kristaps Dzonsons <kristaps@bsd.lv>
  *
 
 /* 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))
+       ((double)(x) / (1000.0 / (double)(p)->engine.ps.scale))
 
 struct glyph {
-       size_t            wx; /* WX in AFM */
+       unsigned short    wx; /* WX in AFM */
 };
 
 struct font {
@@ -373,6 +373,7 @@ static      double            ps_hspan(const struct termp *,
 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_closepage(struct termp *);
 static void              ps_end(struct termp *);
 static void              ps_endline(struct termp *);
 static void              ps_fclose(struct termp *);
@@ -382,10 +383,37 @@ static    void              ps_pletter(struct termp *, int);
 static void              ps_printf(struct termp *, const char *, ...);
 static void              ps_putchar(struct termp *, char);
 static void              ps_setfont(struct termp *, enum termfont);
+static struct termp     *pspdf_alloc(char *);
+
+
+void *
+pdf_alloc(char *outopts)
+{
+       struct termp    *p;
+
+       if (NULL == (p = pspdf_alloc(outopts)))
+               return(p);
+
+       p->type = TERMTYPE_PDF;
+       return(p);
+}
 
 
 void *
 ps_alloc(char *outopts)
+{
+       struct termp    *p;
+
+       if (NULL == (p = pspdf_alloc(outopts)))
+               return(p);
+
+       p->type = TERMTYPE_PS;
+       return(p);
+}
+
+
+static struct termp *
+pspdf_alloc(char *outopts)
 {
        struct termp    *p;
        size_t           pagex, pagey, marginx, marginy, lineheight;
@@ -402,7 +430,6 @@ ps_alloc(char *outopts)
        p->endline = ps_endline;
        p->hspan = ps_hspan;
        p->letter = ps_letter;
-       p->type = TERMTYPE_PS;
        p->width = ps_width;
        
        toks[0] = "paper";
@@ -487,7 +514,7 @@ ps_alloc(char *outopts)
 
 
 void
-ps_free(void *arg)
+pspdf_free(void *arg)
 {
        struct termp    *p;
 
@@ -504,7 +531,7 @@ static void
 ps_printf(struct termp *p, const char *fmt, ...)
 {
        va_list          ap;
-       int              pos;
+       int              pos, len;
 
        va_start(ap, fmt);
 
@@ -515,8 +542,10 @@ ps_printf(struct termp *p, const char *fmt, ...)
         */
 
        if ( ! (PS_MARGINS & p->engine.ps.flags)) {
-               vprintf(fmt, ap);
+               len = vprintf(fmt, ap);
                va_end(ap);
+               p->engine.ps.pdfbytes += /* LINTED */
+                       len < 0 ? 0 : (size_t)len;
                return;
        }
 
@@ -529,10 +558,13 @@ ps_printf(struct termp *p, const char *fmt, ...)
        PS_GROWBUF(p, PS_BUFSLOP);
 
        pos = (int)p->engine.ps.psmargcur;
-       vsnprintf(&p->engine.ps.psmarg[pos], PS_BUFSLOP, fmt, ap);
-       p->engine.ps.psmargcur = strlen(p->engine.ps.psmarg);
+       len = vsnprintf(&p->engine.ps.psmarg[pos], PS_BUFSLOP, fmt, ap);
 
        va_end(ap);
+
+       p->engine.ps.psmargcur = strlen(p->engine.ps.psmarg);
+       p->engine.ps.pdfbytes += /* LINTED */
+               len < 0 ? 0 : (size_t)len;
 }
 
 
@@ -545,6 +577,7 @@ ps_putchar(struct termp *p, char c)
 
        if ( ! (PS_MARGINS & p->engine.ps.flags)) {
                putchar(c);
+               p->engine.ps.pdfbytes++;
                return;
        }
 
@@ -556,10 +589,65 @@ ps_putchar(struct termp *p, char c)
 }
 
 
+static void
+ps_closepage(struct termp *p)
+{
+       int              i;
+       size_t           len;
+
+       assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
+       ps_printf(p, "%s", p->engine.ps.psmarg);
+
+       if (TERMTYPE_PS == p->type) {
+               ps_printf(p, "showpage\n");
+       } else {
+               ps_printf(p, "ET\n");
+               len = p->engine.ps.pdfbytes - p->engine.ps.pdflastpg;
+               ps_printf(p, "endstream\n");
+               ps_printf(p, "endobj\n");
+               ps_printf(p, "%zu 0 obj\n", 
+                               p->engine.ps.pdfbody +
+                               (p->engine.ps.pages + 1) * 4 + 1);
+               ps_printf(p, "%zu\n", len);
+               ps_printf(p, "endobj\n");
+               ps_printf(p, "%zu 0 obj\n", 
+                               p->engine.ps.pdfbody +
+                               (p->engine.ps.pages + 1) * 4 + 2);
+               ps_printf(p, "<<\n");
+               ps_printf(p, "/ProcSet [/PDF /Text]\n");
+               ps_printf(p, "/Font <<\n");
+               for (i = 0; i < (int)TERMFONT__MAX; i++) 
+                       ps_printf(p, "/F%d %d 0 R\n", i, 3 + i);
+               ps_printf(p, ">>\n");
+               ps_printf(p, ">>\n");
+               ps_printf(p, "%zu 0 obj\n", 
+                               p->engine.ps.pdfbody +
+                               (p->engine.ps.pages + 1) * 4 + 3);
+               ps_printf(p, "<<\n");
+               ps_printf(p, "/Type /Page\n");
+               ps_printf(p, "/Parent 2 0 R\n");
+               ps_printf(p, "/Resources %zu 0 R\n",
+                               p->engine.ps.pdfbody +
+                               (p->engine.ps.pages + 1) * 4 + 2);
+               ps_printf(p, "/Contents %zu 0 R\n",
+                               p->engine.ps.pdfbody +
+                               (p->engine.ps.pages + 1) * 4);
+               ps_printf(p, ">>\n");
+               ps_printf(p, "endobj\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;
+}
+
+
 /* ARGSUSED */
 static void
 ps_end(struct termp *p)
 {
+       size_t           i, xref;
 
        /*
         * At the end of the file, do one last showpage.  This is the
@@ -570,15 +658,59 @@ ps_end(struct termp *p)
        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");
+               ps_closepage(p);
        }
 
-       printf("%%%%Trailer\n");
-       printf("%%%%Pages: %zu\n", p->engine.ps.pages);
-       printf("%%%%EOF\n");
+       if (TERMTYPE_PS == p->type) {
+               ps_printf(p, "%%%%Trailer\n");
+               ps_printf(p, "%%%%Pages: %zu\n", p->engine.ps.pages);
+               ps_printf(p, "%%%%EOF\n");
+               return;
+       } 
+
+       ps_printf(p, "2 0 obj\n");
+       ps_printf(p, "<<\n");
+       ps_printf(p, "/Type /Pages\n");
+       ps_printf(p, "/MediaBox [0 0 %zu %zu]\n",
+                       (size_t)AFM2PNT(p, p->engine.ps.width),
+                       (size_t)AFM2PNT(p, p->engine.ps.height));
+
+       ps_printf(p, "/Count %zu\n", p->engine.ps.pages);
+       ps_printf(p, "/Kids [");
+
+       for (i = 0; i < p->engine.ps.pages; i++)
+               ps_printf(p, " %zu 0 R", 
+                               p->engine.ps.pdfbody +
+                               (i + 1) * 4 + 3);
+       ps_printf(p, "]\n");
+       ps_printf(p, ">>\n");
+       ps_printf(p, "endobj\n");
+       ps_printf(p, "%zu 0 obj\n",
+                       p->engine.ps.pdfbody +
+                       (p->engine.ps.pages * 4) + 4);
+       ps_printf(p, "<<\n");
+       ps_printf(p, "/Type /Catalog\n");
+       ps_printf(p, "/Pages 2 0 R\n");
+       ps_printf(p, ">>\n");
+       xref = p->engine.ps.pdfbytes;
+       ps_printf(p, "xref\n");
+       ps_printf(p, "0 %zu\n",
+                       p->engine.ps.pdfbody +
+                       (p->engine.ps.pages * 4) + 5);
+       ps_printf(p, "0000000000 65535 f\n");
+       ps_printf(p, "trailer\n");
+       ps_printf(p, "<<\n");
+       ps_printf(p, "/Size %zu\n", 
+                       p->engine.ps.pdfbody +
+                       (p->engine.ps.pages * 4) + 5);
+       ps_printf(p, "/Root %zu 0 R\n", 
+                       p->engine.ps.pdfbody +
+                       (p->engine.ps.pages * 4) + 4);
+       ps_printf(p, "/Info 1 0 R\n");
+       ps_printf(p, ">>\n");
+       ps_printf(p, "startxref\n");
+       ps_printf(p, "%zu\n", xref);
+       ps_printf(p, "%%%%EOF\n");
 }
 
 
@@ -598,6 +730,7 @@ ps_begin(struct termp *p)
                p->engine.ps.psmarg[0] = '\0';
        }
 
+       p->engine.ps.pdfbytes = 0;
        p->engine.ps.psmargcur = 0;
        p->engine.ps.flags = PS_MARGINS;
        p->engine.ps.pscol = p->engine.ps.left;
@@ -627,21 +760,44 @@ ps_begin(struct termp *p)
 
        t = time(NULL);
 
-       printf("%%!PS-Adobe-3.0\n");
-       printf("%%%%Creator: mandoc-%s\n", VERSION);
-       printf("%%%%CreationDate: %s", ctime(&t));
-       printf("%%%%DocumentData: Clean7Bit\n");
-       printf("%%%%Orientation: Portrait\n");
-       printf("%%%%Pages: (atend)\n");
-       printf("%%%%PageOrder: Ascend\n");
-       printf("%%%%DocumentMedia: Default %zu %zu 0 () ()\n",
-                       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");
+       if (TERMTYPE_PS == p->type) {
+               ps_printf(p, "%%!PS-Adobe-3.0\n");
+               ps_printf(p, "%%%%Creator: mandoc-%s\n", VERSION);
+               ps_printf(p, "%%%%CreationDate: %s", ctime(&t));
+               ps_printf(p, "%%%%DocumentData: Clean7Bit\n");
+               ps_printf(p, "%%%%Orientation: Portrait\n");
+               ps_printf(p, "%%%%Pages: (atend)\n");
+               ps_printf(p, "%%%%PageOrder: Ascend\n");
+               ps_printf(p, "%%%%DocumentMedia: "
+                               "Default %zu %zu 0 () ()\n",
+                               (size_t)AFM2PNT(p, p->engine.ps.width),
+                               (size_t)AFM2PNT(p, p->engine.ps.height));
+               ps_printf(p, "%%%%DocumentNeededResources: font");
+
+               for (i = 0; i < (int)TERMFONT__MAX; i++)
+                       ps_printf(p, " %s", fonts[i].name);
+
+               ps_printf(p, "\n%%%%EndComments\n");
+       } else {
+               ps_printf(p, "%%PDF-1.1\n");
+               ps_printf(p, "1 0 obj\n");
+               ps_printf(p, "<<\n");
+               ps_printf(p, "/Creator mandoc-%s\n", VERSION);
+               ps_printf(p, ">>\n");
+               ps_printf(p, "endobj\n");
+
+               for (i = 0; i < (int)TERMFONT__MAX; i++) {
+                       ps_printf(p, "%d 0 obj\n", i + 3);
+                       ps_printf(p, "<<\n");
+                       ps_printf(p, "/Type /Font\n");
+                       ps_printf(p, "/Subtype /Type1\n");
+                       ps_printf(p, "/Name /F%zu\n", i);
+                       ps_printf(p, "/BaseFont /%s\n", fonts[i].name);
+                       ps_printf(p, ">>\n");
+               }
+       }
 
+       p->engine.ps.pdfbody = (size_t)TERMFONT__MAX + 3;
        p->engine.ps.pscol = p->engine.ps.left;
        p->engine.ps.psrow = p->engine.ps.top;
        p->engine.ps.flags |= PS_NEWPAGE;
@@ -660,12 +816,24 @@ ps_pletter(struct termp *p, int c)
         */
 
        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);
+               if (TERMTYPE_PS == p->type) {
+                       ps_printf(p, "%%%%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);
+               } else {
+                       ps_printf(p, "%zu 0 obj\n", 
+                                       p->engine.ps.pdfbody +
+                                       (p->engine.ps.pages + 1) * 4);
+                       ps_printf(p, "<<\n");
+                       ps_printf(p, "/Length %zu 0 R\n", 
+                                       p->engine.ps.pdfbody +
+                                       (p->engine.ps.pages + 1) * 4 + 1);
+                       ps_printf(p, ">>\nstream\n");
+               }
+               p->engine.ps.pdflastpg = p->engine.ps.pdfbytes;
                p->engine.ps.flags &= ~PS_NEWPAGE;
        }
        
@@ -675,9 +843,17 @@ ps_pletter(struct termp *p, int c)
         */
 
        if ( ! (PS_INLINE & p->engine.ps.flags)) {
-               ps_printf(p, "%zu %zu moveto\n(", 
-                               AFM2PNT(p, p->engine.ps.pscol),
-                               AFM2PNT(p, p->engine.ps.psrow));
+               if (TERMTYPE_PS != p->type) {
+                       ps_printf(p, "BT\n/F%d %zu Tf\n", 
+                                       (int)p->engine.ps.lastf,
+                                       p->engine.ps.scale);
+                       ps_printf(p, "%.3f %.3f Td\n(",
+                                       AFM2PNT(p, p->engine.ps.pscol),
+                                       AFM2PNT(p, p->engine.ps.psrow));
+               } else
+                       ps_printf(p, "%.3f %.3f moveto\n(", 
+                                       AFM2PNT(p, p->engine.ps.pscol),
+                                       AFM2PNT(p, p->engine.ps.psrow));
                p->engine.ps.flags |= PS_INLINE;
        }
 
@@ -708,13 +884,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;
+               p->engine.ps.pscol += (size_t)fonts[f].gly[0].wx;
                return;
        } 
 
        ps_putchar(p, (char)c);
        c -= 32;
-       p->engine.ps.pscol += fonts[f].gly[c].wx;
+       p->engine.ps.pscol += (size_t)fonts[f].gly[c].wx;
 }
 
 
@@ -731,7 +907,11 @@ ps_pclose(struct termp *p)
        if ( ! (PS_INLINE & p->engine.ps.flags))
                return;
        
-       ps_printf(p, ") show\n");
+       if (TERMTYPE_PS != p->type) {
+               ps_printf(p, ") Tj\nET\n");
+       } else
+               ps_printf(p, ") show\n");
+
        p->engine.ps.flags &= ~PS_INLINE;
 }
 
@@ -865,13 +1045,7 @@ ps_endline(struct termp *p)
                return;
        }
 
-       assert(p->engine.ps.psmarg && p->engine.ps.psmarg[0]);
-       printf("%s", p->engine.ps.psmarg);
-       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;
+       ps_closepage(p);
 }
 
 
@@ -890,8 +1064,14 @@ ps_setfont(struct termp *p, enum termfont f)
        if (PS_NEWPAGE & p->engine.ps.flags)
                return;
 
-       ps_printf(p, "/%s %zu selectfont\n", 
-                       fonts[(int)f].name, p->engine.ps.scale);
+       if (TERMTYPE_PS == p->type)
+               ps_printf(p, "/%s %zu selectfont\n", 
+                               fonts[(int)f].name, 
+                               p->engine.ps.scale);
+       else
+               ps_printf(p, "/F%d %zu Tf\n", 
+                               (int)f, 
+                               p->engine.ps.scale);
 }
 
 
@@ -901,10 +1081,10 @@ ps_width(const struct termp *p, char c)
 {
 
        if (c <= 32 || c - 32 >= MAXCHAR)
-               return(fonts[(int)TERMFONT_NONE].gly[0].wx);
+               return((size_t)fonts[(int)TERMFONT_NONE].gly[0].wx);
 
        c -= 32;
-       return(fonts[(int)TERMFONT_NONE].gly[(int)c].wx);
+       return((size_t)fonts[(int)TERMFONT_NONE].gly[(int)c].wx);
 }
 
 
@@ -932,14 +1112,14 @@ ps_hspan(const struct termp *p, const struct roffsu *su)
                r = PNT2AFM(p, su->scale * 100);
                break;
        case (SCALE_EM):
-               r = su->scale * 
+               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 * 
+               r = su->scale *
                        fonts[(int)TERMFONT_NONE].gly[110 - 32].wx;
                break;
        case (SCALE_VS):