From ddce0b0ca1b3ae66643ffdf36394eda67117ca14 Mon Sep 17 00:00:00 2001 From: schwarze Date: Sun, 25 Jul 2010 18:05:54 +0000 Subject: [PATCH] Sync to bsd.lv; in particular, pull in lots of bug fixes. 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 --- usr.bin/mandoc/chars.c | 97 +++-- usr.bin/mandoc/chars.h | 10 +- usr.bin/mandoc/chars.in | 744 ++++++++++++++++----------------- usr.bin/mandoc/html.c | 44 +- usr.bin/mandoc/html.h | 3 +- usr.bin/mandoc/main.c | 37 +- usr.bin/mandoc/main.h | 7 +- usr.bin/mandoc/man.c | 3 +- usr.bin/mandoc/man.h | 5 +- usr.bin/mandoc/man_action.c | 5 +- usr.bin/mandoc/man_html.c | 83 +++- usr.bin/mandoc/man_macro.c | 8 +- usr.bin/mandoc/man_term.c | 99 +++-- usr.bin/mandoc/man_validate.c | 54 ++- usr.bin/mandoc/mandoc.1 | 16 +- usr.bin/mandoc/mandoc.c | 247 +++++------ usr.bin/mandoc/mandoc.h | 3 +- usr.bin/mandoc/mdoc.7 | 471 +++++++++++++++------ usr.bin/mandoc/mdoc.h | 63 +-- usr.bin/mandoc/mdoc_argv.c | 10 +- usr.bin/mandoc/mdoc_html.c | 29 +- usr.bin/mandoc/mdoc_term.c | 9 +- usr.bin/mandoc/mdoc_validate.c | 45 +- usr.bin/mandoc/out.c | 279 +++++-------- usr.bin/mandoc/out.h | 10 +- usr.bin/mandoc/roff.c | 12 +- usr.bin/mandoc/term.c | 30 +- usr.bin/mandoc/term.h | 8 +- usr.bin/mandoc/term_ps.c | 290 ++++++++++--- 29 files changed, 1631 insertions(+), 1090 deletions(-) diff --git a/usr.bin/mandoc/chars.c b/usr.bin/mandoc/chars.c index fb3c0b64ddc..ed1f8b0b6cd 100644 --- a/usr.bin/mandoc/chars.c +++ b/usr.bin/mandoc/chars.c @@ -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 + * Copyright (c) 2009, 2010 Kristaps Dzonsons * * 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]); } diff --git a/usr.bin/mandoc/chars.h b/usr.bin/mandoc/chars.h index 8e55ed2c013..b050994b65c 100644 --- a/usr.bin/mandoc/chars.h +++ b/usr.bin/mandoc/chars.h @@ -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 + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * * 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 diff --git a/usr.bin/mandoc/chars.in b/usr.bin/mandoc/chars.in index 39e49923380..ddb772904c7 100644 --- a/usr.bin/mandoc/chars.in +++ b/usr.bin/mandoc/chars.in @@ -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 + * Copyright (c) 2009, 2010 Kristaps Dzonsons * * 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, " ", 7) -CHAR(" ", 1, " ", 1, " ", 7) -CHAR("~", 1, ascii_nbrsp, 1, " ", 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, "̋", 6) -CHAR("a-", 2, "-", 1, "¯", 6) -CHAR("a.", 2, ".", 1, "˙", 6) -CHAR("a^", 2, "^", 1, "̂", 6) -BOTH("\'", 1, "\'", 1, "́", 6) -BOTH("aa", 2, "\'", 1, "́", 6) -BOTH("ga", 2, "`", 1, "̀", 6) -BOTH("`", 1, "`", 1, "̀", 6) -CHAR("ab", 2, "`", 1, "̆", 6) -CHAR("ac", 2, ",", 1, "̧", 6) -CHAR("ad", 2, "\"", 1, "̈", 6) -CHAR("ah", 2, "v", 1, "ˇ", 6) -CHAR("ao", 2, "o", 1, "˚", 6) -CHAR("a~", 2, "~", 1, "̃", 6) -CHAR("ho", 2, ",", 1, "̨", 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, "„", 7) -CHAR("bq", 2, ",", 1, "‚", 7) -BOTH("lq", 2, "``", 2, "“", 7) -BOTH("rq", 2, "\'\'", 2, "”", 7) -CHAR("oq", 2, "`", 1, "‘", 7) -CHAR("cq", 2, "\'", 1, "’", 7) -CHAR("aq", 2, "\'", 1, "\'", 1) -CHAR("dq", 2, "\"", 1, "\"", 1) -CHAR("Fo", 2, "<<", 2, "«", 6) -CHAR("Fc", 2, ">>", 2, "»", 6) -CHAR("fo", 2, "<", 1, "‹", 7) -CHAR("fc", 2, ">", 1, "›", 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, "⟨", 8) -CHAR("ra", 2, ">", 1, "⟩", 8) -CHAR("bv", 2, "|", 1, "⎪", 7) -CHAR("braceex", 7, "|", 1, "⎪", 7) -CHAR("bracketlefttp", 13, "|", 1, "⎡", 7) -CHAR("bracketleftbp", 13, "|", 1, "⎣", 7) -CHAR("bracketleftex", 13, "|", 1, "⎢", 7) -CHAR("bracketrighttp", 14, "|", 1, "⎤", 7) -CHAR("bracketrightbp", 14, "|", 1, "⎦", 7) -CHAR("bracketrightex", 14, "|", 1, "⎥", 7) -CHAR("lt", 2, ",-", 2, "⎧", 7) -CHAR("bracelefttp", 11, ",-", 2, "⎧", 7) -CHAR("lk", 2, "{", 1, "⎨", 7) -CHAR("braceleftmid", 12, "{", 1, "⎨", 7) -CHAR("lb", 2, ",-", 2, "⎩", 7) -CHAR("braceleftbp", 11, "`-", 2, "⎩", 7) -CHAR("braceleftex", 11, "|", 1, "⎪", 7) -CHAR("rt", 2, "-.", 2, "⎫", 7) -CHAR("bracerighttp", 12, "-.", 2, "⎫", 7) -CHAR("rk", 2, "}", 1, "⎬", 7) -CHAR("bracerightmid", 13, "}", 1, "⎬", 7) -CHAR("rb", 2, "-\'", 2, "⎭", 7) -CHAR("bracerightbp", 12, "-\'", 2, "⎭", 7) -CHAR("bracerightex", 12, "|", 1, "⎪", 7) -CHAR("parenlefttp", 11, "/", 1, "⎛", 7) -CHAR("parenleftbp", 11, "\\", 1, "⎝", 7) -CHAR("parenleftex", 11, "|", 1, "⎜", 7) -CHAR("parenrighttp", 12, "\\", 1, "⎞", 7) -CHAR("parenrightbp", 12, "/", 1, "⎠", 7) -CHAR("parenrightex", 12, "|", 1, "⎟", 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, "Α", 6) -CHAR("*B", 2, "B", 1, "Β", 6) -CHAR("*G", 2, "|", 1, "Γ", 6) -CHAR("*D", 2, "/\\", 2, "Δ", 6) -CHAR("*E", 2, "E", 1, "Ε", 6) -CHAR("*Z", 2, "Z", 1, "Ζ", 6) -CHAR("*Y", 2, "H", 1, "Η", 6) -CHAR("*H", 2, "O", 1, "Θ", 6) -CHAR("*I", 2, "I", 1, "Ι", 6) -CHAR("*K", 2, "K", 1, "Κ", 6) -CHAR("*L", 2, "/\\", 2, "Λ", 6) -CHAR("*M", 2, "M", 1, "Μ", 6) -CHAR("*N", 2, "N", 1, "Ν", 6) -CHAR("*C", 2, "H", 1, "Ξ", 6) -CHAR("*O", 2, "O", 1, "Ο", 6) -CHAR("*P", 2, "TT", 2, "Π", 6) -CHAR("*R", 2, "P", 1, "Ρ", 6) -CHAR("*S", 2, ">", 1, "Σ", 6) -CHAR("*T", 2, "T", 1, "Τ", 6) -CHAR("*U", 2, "Y", 1, "Υ", 6) -CHAR("*F", 2, "O_", 1, "Φ", 6) -CHAR("*X", 2, "X", 1, "Χ", 6) -CHAR("*Q", 2, "Y", 1, "Ψ", 6) -CHAR("*W", 2, "O", 1, "Ω", 6) -CHAR("*a", 2, "a", 1, "α", 6) -CHAR("*b", 2, "B", 1, "β", 6) -CHAR("*g", 2, "y", 1, "γ", 6) -CHAR("*d", 2, "d", 1, "δ", 6) -CHAR("*e", 2, "e", 1, "ε", 6) -CHAR("*z", 2, "C", 1, "ζ", 6) -CHAR("*y", 2, "n", 1, "η", 6) -CHAR("*h", 2, "0", 1, "θ", 6) -CHAR("*i", 2, "i", 1, "ι", 6) -CHAR("*k", 2, "k", 1, "κ", 6) -CHAR("*l", 2, "\\", 1, "λ", 6) -CHAR("*m", 2, "u", 1, "μ", 6) -CHAR("*n", 2, "v", 1, "ν", 6) -CHAR("*c", 2, "E", 1, "ξ", 6) -CHAR("*o", 2, "o", 1, "ο", 6) -CHAR("*p", 2, "n", 1, "π", 6) -CHAR("*r", 2, "p", 1, "ρ", 6) -CHAR("*s", 2, "o", 1, "σ", 6) -CHAR("*t", 2, "t", 1, "τ", 6) -CHAR("*u", 2, "u", 1, "υ", 6) -CHAR("*f", 2, "o", 1, "ϕ", 6) -CHAR("*x", 2, "x", 1, "χ", 6) -CHAR("*q", 2, "u", 1, "ψ", 6) -CHAR("*w", 2, "w", 1, "ω", 6) -CHAR("+h", 2, "0", 1, "ϑ", 6) -CHAR("+f", 2, "o", 1, "φ", 6) -CHAR("+p", 2, "w", 1, "ϖ", 6) -CHAR("+e", 2, "e", 1, "ϵ", 7) -CHAR("ts", 2, "s", 1, "ς", 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, "Ç", 6) -CHAR(",c", 2, "c", 1, "ç", 6) -CHAR("/L", 2, "L", 1, "Ł", 6) -CHAR("/O", 2, "O", 1, "Ø", 6) -CHAR("/l", 2, "l", 1, "ł", 6) -CHAR("/o", 2, "o", 1, "ø", 6) -CHAR("oA", 2, "A", 1, "Å", 6) -CHAR("oa", 2, "a", 1, "å", 6) -CHAR(":A", 2, "A", 1, "Ä", 6) -CHAR(":E", 2, "E", 1, "Ë", 6) -CHAR(":I", 2, "I", 1, "Ï", 6) -CHAR(":O", 2, "O", 1, "Ö", 6) -CHAR(":U", 2, "U", 1, "Ü", 6) -CHAR(":a", 2, "a", 1, "ä", 6) -CHAR(":e", 2, "e", 1, "ë", 6) -CHAR(":i", 2, "i", 1, "ï", 6) -CHAR(":o", 2, "o", 1, "õ", 6) -CHAR(":u", 2, "u", 1, "ü", 6) -CHAR(":y", 2, "y", 1, "ÿ", 6) -CHAR("\'A", 2, "A", 1, "Á", 6) -CHAR("\'E", 2, "E", 1, "É", 6) -CHAR("\'I", 2, "I", 1, "Í", 6) -CHAR("\'O", 2, "O", 1, "Ó", 6) -CHAR("\'U", 2, "U", 1, "Ú", 6) -CHAR("\'a", 2, "a", 1, "á", 6) -CHAR("\'e", 2, "e", 1, "é", 6) -CHAR("\'i", 2, "i", 1, "í", 6) -CHAR("\'o", 2, "o", 1, "ó", 6) -CHAR("\'u", 2, "u", 1, "ú", 6) -CHAR("^A", 2, "A", 1, "Â", 6) -CHAR("^E", 2, "E", 1, "Ê", 6) -CHAR("^I", 2, "I", 1, "Î", 6) -CHAR("^O", 2, "O", 1, "Ô", 6) -CHAR("^U", 2, "U", 1, "Û", 6) -CHAR("^a", 2, "a", 1, "â", 6) -CHAR("^e", 2, "e", 1, "ê", 6) -CHAR("^i", 2, "i", 1, "î", 6) -CHAR("^o", 2, "o", 1, "ô", 6) -CHAR("^u", 2, "u", 1, "û", 6) -CHAR("`A", 2, "A", 1, "À", 6) -CHAR("`E", 2, "E", 1, "È", 6) -CHAR("`I", 2, "I", 1, "Ì", 6) -CHAR("`O", 2, "O", 1, "Ò", 6) -CHAR("`U", 2, "U", 1, "Ù", 6) -CHAR("`a", 2, "a", 1, "à", 6) -CHAR("`e", 2, "e", 1, "è", 6) -CHAR("`i", 2, "i", 1, "ì", 6) -CHAR("`o", 2, "o", 1, "ò", 6) -CHAR("`u", 2, "u", 1, "ù", 6) -CHAR("~A", 2, "A", 1, "Ã", 6) -CHAR("~N", 2, "N", 1, "Ñ", 6) -CHAR("~O", 2, "O", 1, "Õ", 6) -CHAR("~a", 2, "a", 1, "ã", 6) -CHAR("~n", 2, "n", 1, "ñ", 6) -CHAR("~o", 2, "o", 1, "õ", 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, "←", 7) -CHAR("->", 2, "->", 2, "→", 7) -CHAR("<>", 2, "<>", 2, "↔", 7) -CHAR("da", 2, "v", 1, "↓", 7) -BOTH("ua", 2, "^", 1, "↑", 7) -BOTH("va", 2, "^v", 2, "↕", 7) -CHAR("lA", 2, "<=", 2, "⇐", 7) -CHAR("rA", 2, "=>", 2, "⇒", 7) -CHAR("hA", 2, "<=>", 3, "⇔", 7) -CHAR("dA", 2, "v", 1, "⇓", 7) -CHAR("uA", 2, "^", 1, "⇑", 7) -CHAR("vA", 2, "^=v", 3, "⇕", 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, "∧", 7) -CHAR("OR", 2, "v", 1, "∨", 7) -CHAR("no", 2, "~", 1, "¬", 6) -CHAR("tno", 3, "~", 1, "¬", 6) -CHAR("te", 2, "3", 1, "∃", 7) -CHAR("fa", 2, "V", 1, "∀", 7) -CHAR("st", 2, "-)", 2, "∋", 7) -CHAR("tf", 2, ".:.", 3, "∴", 7) -CHAR("3d", 2, ".:.", 3, "∴", 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, "+", 5) -CHAR("mi", 2, "-", 1, "−", 7) -CHAR("-", 1, "-", 1, "-", 1) -CHAR("-+", 2, "-+", 2, "∓", 7) -CHAR("+-", 2, "+-", 2, "±", 6) -CHAR("t+-", 3, "+-", 2, "±", 6) -CHAR("pc", 2, ".", 1, "·", 6) -CHAR("md", 2, ".", 1, "⋅", 7) -CHAR("mu", 2, "x", 1, "×", 6) -CHAR("tmu", 3, "x", 1, "×", 6) -CHAR("c*", 2, "x", 1, "⊗", 7) -CHAR("c+", 2, "+", 1, "⊕", 7) -CHAR("di", 2, "-:-", 3, "÷", 6) -CHAR("tdi", 3, "-:-", 3, "÷", 6) -CHAR("f/", 2, "/", 1, "⁄", 7) -CHAR("**", 2, "*", 1, "∗", 7) -BOTH("<=", 2, "<=", 2, "≤", 7) -BOTH(">=", 2, ">=", 2, "≥", 7) -CHAR("<<", 2, "<<", 2, "≪", 7) -CHAR(">>", 2, ">>", 2, "≫", 7) -CHAR("eq", 2, "=", 1, "=", 5) -CHAR("!=", 2, "!=", 2, "≠", 7) -CHAR("==", 2, "==", 2, "≡", 7) -CHAR("ne", 2, "!==", 3, "≢", 7) -CHAR("=~", 2, "=~", 2, "≅", 7) -CHAR("-~", 2, "-~", 2, "≃", 7) -CHAR("ap", 2, "~", 1, "∼", 7) -CHAR("~~", 2, "~~", 2, "≈", 7) -CHAR("~=", 2, "~=", 2, "≌", 7) -CHAR("pt", 2, "oc", 2, "∝", 7) -CHAR("es", 2, "{}", 2, "∅", 7) -CHAR("mo", 2, "E", 1, "∈", 7) -CHAR("nm", 2, "!E", 2, "∉", 7) -CHAR("sb", 2, "(=", 2, "⊂", 7) -CHAR("nb", 2, "(!=", 3, "⊄", 7) -CHAR("sp", 2, "=)", 2, "⊃", 7) -CHAR("nc", 2, "!=)", 3, "⊅", 7) -CHAR("ib", 2, "(=", 2, "⊆", 7) -CHAR("ip", 2, "=)", 2, "⊇", 7) -CHAR("ca", 2, "(^)", 3, "∩", 7) -CHAR("cu", 2, "U", 1, "∪", 7) -CHAR("/_", 2, "/_", 2, "∠", 7) -CHAR("pp", 2, "_|_", 3, "⊥", 7) -CHAR("is", 2, "I", 1, "∫", 7) -CHAR("integral", 8, "I", 1, "∫", 7) -CHAR("sum", 3, "E", 1, "∑", 7) -CHAR("product", 7, "TT", 2, "∏", 7) -CHAR("coproduct", 9, "U", 1, "∐", 7) -CHAR("gr", 2, "V", 1, "∇", 7) -CHAR("sr", 2, "\\/", 2, "√", 7) -CHAR("sqrt", 4, "\\/", 2, "√", 7) -CHAR("lc", 2, "|~", 2, "⌈", 7) -CHAR("rc", 2, "~|", 2, "⌉", 7) -CHAR("lf", 2, "|_", 2, "⌊", 7) -CHAR("rf", 2, "_|", 2, "⌋", 7) -CHAR("if", 2, "oo", 2, "∞", 7) -CHAR("Ah", 2, "N", 1, "ℵ", 7) -CHAR("Im", 2, "I", 1, "ℑ", 7) -CHAR("Re", 2, "R", 1, "ℜ", 7) -CHAR("pd", 2, "a", 1, "∂", 7) -CHAR("-h", 2, "/h", 2, "ℏ", 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, "ff", 8) -CHAR("fi", 2, "fi", 2, "fi", 8) -CHAR("fl", 2, "fl", 2, "fl", 8) -CHAR("Fi", 2, "ffi", 3, "ffi", 8) -CHAR("Fl", 2, "ffl", 3, "ffl", 8) -BOTH("AE", 2, "AE", 2, "Æ", 6) -BOTH("ae", 2, "ae", 2, "æ", 6) -CHAR("OE", 2, "OE", 2, "Œ", 6) -CHAR("oe", 2, "oe", 2, "œ", 6) -CHAR("ss", 2, "ss", 2, "ß", 6) -CHAR("IJ", 2, "IJ", 2, "IJ", 6) -CHAR("ij", 2, "ij", 2, "ij", 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, "Ð", 6) -CHAR("Sd", 2, "o", 1, "ð", 6) -CHAR("TP", 2, "b", 1, "Þ", 6) -CHAR("Tp", 2, "b", 1, "þ", 6) -CHAR(".i", 2, "i", 1, "ı", 6) -CHAR(".j", 2, "j", 1, "ȷ", 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, "¢", 6) -CHAR("Eu", 2, "EUR", 3, "€", 7) -CHAR("eu", 2, "EUR", 3, "€", 7) -CHAR("Ye", 2, "Y", 1, "¥", 6) -CHAR("Po", 2, "L", 1, "£", 6) -CHAR("Cs", 2, "x", 1, "¤", 6) -CHAR("Fn", 2, "f", 1, "ƒ", 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, "—", 7) -STRING("PI", 2, "pi", 2, "π", 6) -STRING("L\"", 2, "``", 2, "“", 7) -STRING("R\"", 2, "\'\'", 2, "”", 7) -STRING("C+", 2, "C++", 3, "C++", 3) -STRING("C`", 2, "`", 1, "‘", 7) -STRING("C\'", 2, "\'", 1, "’", 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, "̈", 6) -STRING("8", 1, "B", 1, "β", 6) -STRING("o", 1, "o", 1, "°", 6) -STRING("D-", 2, "D", 1, "Ð", 6) -STRING("d-", 2, "o", 1, "ð", 6) -STRING("Th", 2, "b", 1, "Þ", 6) -STRING("th", 2, "b", 1, "þ", 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, "&", 5) -STRING("Ba", 2, "|", 1, "|", 1) -STRING("Ge", 2, ">=", 2, "≥", 7) -STRING("Gt", 2, ">", 1, ">", 4) -STRING("If", 2, "infinity", 8, "infinity", 8) -STRING("Le", 2, "<=", 2, "≤", 7) -STRING("Lq", 2, "``", 2, "“", 7) -STRING("Lt", 2, "<", 1, "<", 4) -STRING("Na", 2, "NaN", 3, "NaN", 3) -STRING("Ne", 2, "!=", 2, "≠", 7) -STRING("Pi", 2, "pi", 2, "π", 6) -STRING("Pm", 2, "+-", 2, "±", 6) -STRING("R", 1, "(R)", 3, "®", 6) -STRING("Rq", 2, "\'\'", 2, "”", 7) -STRING("Tm", 2, "tm", 2, "™", 7) -STRING("left-bracket", 12, "[", 1, "[", 1) -STRING("left-parenthesis", 16, "(", 1, "(", 1) -STRING("left-singlequote", 16, "`", 1, "‘", 7) -STRING("lp", 2, "(", 1, "(", 1) -STRING("q", 1, "\"", 1, """, 6) -STRING("quote-left", 10, "`", 1, "‘", 7) -STRING("quote-right", 11, "\'", 1, "’", 7) -STRING("right-bracket", 13, "]", 1, "]", 1) -STRING("right-parenthesis", 17, ")", 1, ")", 1) -STRING("right-singlequote", 17, "\'", 1, "’", 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, "|", 6) -CHAR("br", 2, "|", 1, "│", 7) -CHAR("ul", 2, "_", 1, "_", 5) -CHAR("rl", 2, "-", 1, "‾", 7) -CHAR("bb", 2, "|", 1, "¦", 6) -CHAR("sl", 2, "/", 1, "/", 5) -CHAR("rs", 2, "\\", 1, "\", 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, "○", 7) -CHAR("bu", 2, "o", 1, "•", 7) -CHAR("dd", 2, "=", 1, "‡", 7) -CHAR("dg", 2, "-", 1, "†", 7) -CHAR("lz", 2, "<>", 2, "◊", 7) -CHAR("sq", 2, "[]", 2, "□", 7) -CHAR("ps", 2, "9|", 2, "¶", 6) -CHAR("sc", 2, "S", 1, "§", 6) -CHAR("lh", 2, "<=", 2, "☜", 7) -CHAR("rh", 2, "=>", 2, "☞", 7) -CHAR("at", 2, "@", 1, "@", 5) -CHAR("sh", 2, "#", 1, "#", 5) -CHAR("CR", 2, "_|", 2, "↵", 7) -CHAR("OK", 2, "\\/", 2, "✓", 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, "©", 6) -CHAR("rg", 2, "(R)", 3, "®", 6) -CHAR("tm", 2, "tm", 2, "™", 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, "¡", 6) -CHAR("r?", 2, "c", 1, "¿", 6) -CHAR("em", 2, "--", 2, "—", 7) -CHAR("en", 2, "-", 1, "–", 7) -CHAR("hy", 2, "-", 1, "‐", 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, "°", 6) -CHAR("%0", 2, "%o", 2, "‰", 7) -CHAR("fm", 2, "\'", 1, "′", 7) -CHAR("sd", 2, "\"", 1, "″", 7) -CHAR("mc", 2, "mu", 2, "µ", 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 diff --git a/usr.bin/mandoc/html.c b/usr.bin/mandoc/html.c index 16cdb29fd8e..eb9ebda5be3 100644 --- a/usr.bin/mandoc/html.c +++ b/usr.bin/mandoc/html.c @@ -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 * @@ -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(" "); } + 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 diff --git a/usr.bin/mandoc/html.h b/usr.bin/mandoc/html.h index bd973499cc0..e719721e61c 100644 --- a/usr.bin/mandoc/html.h +++ b/usr.bin/mandoc/html.h @@ -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 * @@ -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; diff --git a/usr.bin/mandoc/main.c b/usr.bin/mandoc/main.c index 53b4e7b81e3..512581e4e30 100644 --- a/usr.bin/mandoc/main.c +++ b/usr.bin/mandoc/main.c @@ -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 * Copyright (c) 2010 Ingo Schwarze @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -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); diff --git a/usr.bin/mandoc/main.h b/usr.bin/mandoc/main.h index 7d38a729537..2cb020dedc2 100644 --- a/usr.bin/mandoc/main.h +++ b/usr.bin/mandoc/main.h @@ -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 + * Copyright (c) 2009, 2010 Kristaps Dzonsons * * 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 *); diff --git a/usr.bin/mandoc/man.c b/usr.bin/mandoc/man.c index cb994e86653..95b176237af 100644 --- a/usr.bin/mandoc/man.c +++ b/usr.bin/mandoc/man.c @@ -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 * @@ -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; diff --git a/usr.bin/mandoc/man.h b/usr.bin/mandoc/man.h index b56a2863e68..06fdc75a5ed 100644 --- a/usr.bin/mandoc/man.h +++ b/usr.bin/mandoc/man.h @@ -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 + * Copyright (c) 2009, 2010 Kristaps Dzonsons * * 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 }; diff --git a/usr.bin/mandoc/man_action.c b/usr.bin/mandoc/man_action.c index 8550fafa97e..eda931be653 100644 --- a/usr.bin/mandoc/man_action.c +++ b/usr.bin/mandoc/man_action.c @@ -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 + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * * 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 */ }; diff --git a/usr.bin/mandoc/man_html.c b/usr.bin/mandoc/man_html.c index 8b77f129bb6..b127639e546 100644 --- a/usr.bin/mandoc/man_html.c +++ b/usr.bin/mandoc/man_html.c @@ -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 * @@ -36,8 +36,14 @@ #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) diff --git a/usr.bin/mandoc/man_macro.c b/usr.bin/mandoc/man_macro.c index 84541d3cf90..7e01af81161 100644 --- a/usr.bin/mandoc/man_macro.c +++ b/usr.bin/mandoc/man_macro.c @@ -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 + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * * 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) { diff --git a/usr.bin/mandoc/man_term.c b/usr.bin/mandoc/man_term.c index dfb4463f1e7..9c3389d9b1f 100644 --- a/usr.bin/mandoc/man_term.c +++ b/usr.bin/mandoc/man_term.c @@ -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 * @@ -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); } diff --git a/usr.bin/mandoc/man_validate.c b/usr.bin/mandoc/man_validate.c index 8658846720a..cb7ab9b8dc3 100644 --- a/usr.bin/mandoc/man_validate.c +++ b/usr.bin/mandoc/man_validate.c @@ -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 + * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons * * 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 #include #include +#include #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); diff --git a/usr.bin/mandoc/mandoc.1 b/usr.bin/mandoc/mandoc.1 index e0fa0b163df..fb7b4db418f 100644 --- a/usr.bin/mandoc/mandoc.1 +++ b/usr.bin/mandoc/mandoc.1 @@ -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 .\" @@ -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 diff --git a/usr.bin/mandoc/mandoc.c b/usr.bin/mandoc/mandoc.c index aeef2911def..68d3451042a 100644 --- a/usr.bin/mandoc/mandoc.c +++ b/usr.bin/mandoc/mandoc.c @@ -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 * @@ -27,187 +27,161 @@ #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 */ diff --git a/usr.bin/mandoc/mandoc.h b/usr.bin/mandoc/mandoc.h index 53b239b57f5..eb79fc65a4a 100644 --- a/usr.bin/mandoc/mandoc.h +++ b/usr.bin/mandoc/mandoc.h @@ -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 * @@ -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 */ diff --git a/usr.bin/mandoc/mdoc.7 b/usr.bin/mandoc/mdoc.7 index e00564aac5c..1d64e581ead 100644 --- a/usr.bin/mandoc/mdoc.7 +++ b/usr.bin/mandoc/mdoc.7 @@ -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 .\" Copyright (c) 2010 Ingo Schwarze @@ -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 -.\" . diff --git a/usr.bin/mandoc/mdoc.h b/usr.bin/mandoc/mdoc.h index 738db7976ef..7868408df2e 100644 --- a/usr.bin/mandoc/mdoc.h +++ b/usr.bin/mandoc/mdoc.h @@ -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 * @@ -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; diff --git a/usr.bin/mandoc/mdoc_argv.c b/usr.bin/mandoc/mdoc_argv.c index 61d5dbbce58..166ced62600 100644 --- a/usr.bin/mandoc/mdoc_argv.c +++ b/usr.bin/mandoc/mdoc_argv.c @@ -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 * @@ -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) { diff --git a/usr.bin/mandoc/mdoc_html.c b/usr.bin/mandoc/mdoc_html.c index b088164f931..73c7aa5aa8a 100644 --- a/usr.bin/mandoc/mdoc_html.c +++ b/usr.bin/mandoc/mdoc_html.c @@ -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 * @@ -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; } diff --git a/usr.bin/mandoc/mdoc_term.c b/usr.bin/mandoc/mdoc_term.c index 629dcdba5cc..0dce300ba1b 100644 --- a/usr.bin/mandoc/mdoc_term.c +++ b/usr.bin/mandoc/mdoc_term.c @@ -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 * Copyright (c) 2010 Ingo Schwarze @@ -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; } diff --git a/usr.bin/mandoc/mdoc_validate.c b/usr.bin/mandoc/mdoc_validate.c index 2b1fc088bf7..9cffeaae31d 100644 --- a/usr.bin/mandoc/mdoc_validate.c +++ b/usr.bin/mandoc/mdoc_validate.c @@ -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 * @@ -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 diff --git a/usr.bin/mandoc/out.c b/usr.bin/mandoc/out.c index f79643f6964..bbde1ea9ed7 100644 --- a/usr.bin/mandoc/out.c +++ b/usr.bin/mandoc/out.c @@ -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 + * Copyright (c) 2009, 2010 Kristaps Dzonsons * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,26 +25,6 @@ #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); } diff --git a/usr.bin/mandoc/out.h b/usr.bin/mandoc/out.h index b32f8c7a93f..bbd24ab54be 100644 --- a/usr.bin/mandoc/out.h +++ b/usr.bin/mandoc/out.h @@ -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 + * Copyright (c) 2009 Kristaps Dzonsons * * 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 */ diff --git a/usr.bin/mandoc/roff.c b/usr.bin/mandoc/roff.c index 4522f786a82..0d9fd8cc78e 100644 --- a/usr.bin/mandoc/roff.c +++ b/usr.bin/mandoc/roff.c @@ -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 * Copyright (c) 2010 Ingo Schwarze @@ -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); /* diff --git a/usr.bin/mandoc/term.c b/usr.bin/mandoc/term.c index 459c17a3d7b..231616c31c8 100644 --- a/usr.bin/mandoc/term.c +++ b/usr.bin/mandoc/term.c @@ -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 * Copyright (c) 2010 Ingo Schwarze @@ -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 */ diff --git a/usr.bin/mandoc/term.h b/usr.bin/mandoc/term.h index ff2585a814e..fd67cd9493f 100644 --- a/usr.bin/mandoc/term.h +++ b/usr.bin/mandoc/term.h @@ -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 * @@ -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 { diff --git a/usr.bin/mandoc/term_ps.c b/usr.bin/mandoc/term_ps.c index 44fa34e6f10..5d570c618b0 100644 --- a/usr.bin/mandoc/term_ps.c +++ b/usr.bin/mandoc/term_ps.c @@ -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 * @@ -39,10 +39,10 @@ /* 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): -- 2.20.1