diff options
author | Yuri Pankov <yuri.pankov@nexenta.com> | 2016-07-29 15:19:48 +0300 |
---|---|---|
committer | Richard Lowe <richlowe@richlowe.net> | 2016-08-17 17:00:11 -0400 |
commit | 371584c2eae4cf827fd406ba26c14f021adaaa70 (patch) | |
tree | 42632bedb51ee7aa4c71b3480230cf2bc0789281 | |
parent | 7a8b8fd18ff115f0caa89183db5373afb568b630 (diff) | |
download | illumos-joyent-371584c2eae4cf827fd406ba26c14f021adaaa70.tar.gz |
7243 update mdocml to 1.13.4
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
77 files changed, 5906 insertions, 5760 deletions
diff --git a/exception_lists/cstyle b/exception_lists/cstyle index 5c2223536f..1705474800 100644 --- a/exception_lists/cstyle +++ b/exception_lists/cstyle @@ -81,12 +81,14 @@ usr/src/cmd/krb5/slave/kprop.h usr/src/cmd/krb5/slave/kpropd.c usr/src/cmd/mandoc/att.c usr/src/cmd/mandoc/chars.c -usr/src/cmd/mandoc/compat_fgetln.c +usr/src/cmd/mandoc/compat_ohash.c +usr/src/cmd/mandoc/compat_ohash.h usr/src/cmd/mandoc/compat_reallocarray.c +usr/src/cmd/mandoc/compat_strtonum.c usr/src/cmd/mandoc/config.h -usr/src/cmd/mandoc/eqn.c usr/src/cmd/mandoc/eqn_html.c usr/src/cmd/mandoc/eqn_term.c +usr/src/cmd/mandoc/eqn.c usr/src/cmd/mandoc/html.c usr/src/cmd/mandoc/html.h usr/src/cmd/mandoc/lib.c @@ -96,43 +98,53 @@ usr/src/cmd/mandoc/libmdoc.h usr/src/cmd/mandoc/libroff.h usr/src/cmd/mandoc/main.c usr/src/cmd/mandoc/main.h -usr/src/cmd/mandoc/man.c -usr/src/cmd/mandoc/man.h usr/src/cmd/mandoc/man_hash.c usr/src/cmd/mandoc/man_html.c usr/src/cmd/mandoc/man_macro.c usr/src/cmd/mandoc/man_term.c usr/src/cmd/mandoc/man_validate.c +usr/src/cmd/mandoc/man.c +usr/src/cmd/mandoc/man.h +usr/src/cmd/mandoc/manconf.h +usr/src/cmd/mandoc/mandoc_aux.c +usr/src/cmd/mandoc/mandoc_aux.h +usr/src/cmd/mandoc/mandoc_ohash.c +usr/src/cmd/mandoc/mandoc_ohash.h usr/src/cmd/mandoc/mandoc.c usr/src/cmd/mandoc/mandoc.h -usr/src/cmd/mandoc/mandoc_aux.c usr/src/cmd/mandoc/manpath.c -usr/src/cmd/mandoc/mdoc.c -usr/src/cmd/mandoc/mdoc.h +usr/src/cmd/mandoc/mansearch.h usr/src/cmd/mandoc/mdoc_argv.c usr/src/cmd/mandoc/mdoc_hash.c usr/src/cmd/mandoc/mdoc_html.c usr/src/cmd/mandoc/mdoc_macro.c usr/src/cmd/mandoc/mdoc_man.c +usr/src/cmd/mandoc/mdoc_state.c usr/src/cmd/mandoc/mdoc_term.c usr/src/cmd/mandoc/mdoc_validate.c +usr/src/cmd/mandoc/mdoc.c +usr/src/cmd/mandoc/mdoc.h usr/src/cmd/mandoc/msec.c usr/src/cmd/mandoc/out.c usr/src/cmd/mandoc/out.h usr/src/cmd/mandoc/preconv.c usr/src/cmd/mandoc/read.c +usr/src/cmd/mandoc/roff_int.h usr/src/cmd/mandoc/roff.c +usr/src/cmd/mandoc/roff.h usr/src/cmd/mandoc/st.c -usr/src/cmd/mandoc/tbl.c +usr/src/cmd/mandoc/tag.c +usr/src/cmd/mandoc/tag.h usr/src/cmd/mandoc/tbl_data.c usr/src/cmd/mandoc/tbl_html.c usr/src/cmd/mandoc/tbl_layout.c usr/src/cmd/mandoc/tbl_opts.c usr/src/cmd/mandoc/tbl_term.c -usr/src/cmd/mandoc/term.c -usr/src/cmd/mandoc/term.h +usr/src/cmd/mandoc/tbl.c usr/src/cmd/mandoc/term_ascii.c usr/src/cmd/mandoc/term_ps.c +usr/src/cmd/mandoc/term.c +usr/src/cmd/mandoc/term.h usr/src/cmd/mandoc/tree.c usr/src/common/bzip2/bzlib.h usr/src/common/bzip2/crctable.c diff --git a/exception_lists/hdrchk b/exception_lists/hdrchk index f99ea05edc..c6fc1818f7 100644 --- a/exception_lists/hdrchk +++ b/exception_lists/hdrchk @@ -31,6 +31,7 @@ usr/src/cmd/krb5/ldap_util/kdb5_ldap_services.h usr/src/cmd/krb5/ldap_util/kdb5_ldap_util.h usr/src/cmd/krb5/slave/kprop.h usr/src/cmd/localedef/localedef.h +usr/src/cmd/mandoc/compat_ohash.h usr/src/cmd/mandoc/config.h usr/src/cmd/mandoc/html.h usr/src/cmd/mandoc/libman.h @@ -39,12 +40,16 @@ usr/src/cmd/mandoc/libmdoc.h usr/src/cmd/mandoc/libroff.h usr/src/cmd/mandoc/main.h usr/src/cmd/mandoc/man.h -usr/src/cmd/mandoc/mandoc.h +usr/src/cmd/mandoc/manconf.h usr/src/cmd/mandoc/mandoc_aux.h -usr/src/cmd/mandoc/manpath.h +usr/src/cmd/mandoc/mandoc_ohash.h +usr/src/cmd/mandoc/mandoc.h usr/src/cmd/mandoc/mansearch.h usr/src/cmd/mandoc/mdoc.h usr/src/cmd/mandoc/out.h +usr/src/cmd/mandoc/roff_int.h +usr/src/cmd/mandoc/roff.h +usr/src/cmd/mandoc/tag.h usr/src/cmd/mandoc/term.h usr/src/grub/grub-0.97/stage2/shared.h usr/src/lib/gss_mechs/mech_krb5/et/error_table.h diff --git a/usr/src/cmd/mandoc/Makefile.common b/usr/src/cmd/mandoc/Makefile.common index d4e95ffbfd..a08580ca1a 100644 --- a/usr/src/cmd/mandoc/Makefile.common +++ b/usr/src/cmd/mandoc/Makefile.common @@ -11,7 +11,7 @@ # # Copyright 2014 Garrett D'Amore <garrett@damore.org> -# Copyright 2015 Nexenta Systems, Inc. All rights reserved. +# Copyright 2016 Nexenta Systems, Inc. # PROG= mandoc @@ -33,12 +33,14 @@ OBJS= att.o \ man_validate.o \ mandoc.o \ mandoc_aux.o \ + mandoc_ohash.o \ mdoc.o \ mdoc_argv.o \ mdoc_hash.o \ mdoc_html.o \ mdoc_macro.o \ mdoc_man.o \ + mdoc_state.o \ mdoc_term.o \ mdoc_validate.o \ msec.o \ @@ -47,6 +49,7 @@ OBJS= att.o \ roff.o \ preconv.o \ st.o \ + tag.o \ tbl.o \ tbl_data.o \ tbl_html.o \ @@ -58,10 +61,13 @@ OBJS= att.o \ term_ps.o \ tree.o -OBJS += compat_fgetln.o \ +OBJS += compat_ohash.o \ compat_reallocarray.o \ compat_strtonum.o CFLAGS += $(CC_VERBOSE) +C99MODE = $(C99_ENABLE) CPPFLAGS += -DOSNAME="\"illumos\"" + +LDLIBS += -lz diff --git a/usr/src/cmd/mandoc/THIRDPARTYLICENSE b/usr/src/cmd/mandoc/THIRDPARTYLICENSE index 080c04fa26..becdb9656a 100644 --- a/usr/src/cmd/mandoc/THIRDPARTYLICENSE +++ b/usr/src/cmd/mandoc/THIRDPARTYLICENSE @@ -1,17 +1,19 @@ -$Id: LICENSE,v 1.7 2015/02/16 14:56:22 schwarze Exp $ +$Id: LICENSE,v 1.12 2016/07/07 23:46:36 schwarze Exp $ With the exceptions noted below, all code and documentation contained in the mdocml toolkit is protected by the Copyright of the following developers: Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> -Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> +Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org> Copyright (c) 2009, 2010, 2011, 2012 Joerg Sonnenberger <joerg@netbsd.org> Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> +Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org> Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org> Copyright (c) 1998, 2004, 2010 Todd C. Miller <Todd.Miller@courtesan.com> Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> Copyright (c) 2004 Ted Unangst <tedu@openbsd.org> +Copyright (c) 1994 Christos Zoulas <christos@netbsd.org> Copyright (c) 2003, 2007, 2008, 2014 Jason McIntyre <jmc@openbsd.org> See the individual source files for information about who contributed @@ -32,16 +34,3 @@ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - -The following files included from outside sources are protected by -other people's Copyright and are distributed under a 3-clause BSD -license; see these individual files for details. - -compat_fts.c, compat_fts.h, -compat_getsubopt.c, compat_strcasestr.c, compat_strsep.c, -man.1: -Copyright (c) 1989,1990,1993,1994 The Regents of the University of California - -compat_fgetln.c: -Copyright (c) 1998 The NetBSD Foundation, Inc. diff --git a/usr/src/cmd/mandoc/att.c b/usr/src/cmd/mandoc/att.c index a1703ebcc6..872f982395 100644 --- a/usr/src/cmd/mandoc/att.c +++ b/usr/src/cmd/mandoc/att.c @@ -1,4 +1,4 @@ -/* $Id: att.c,v 1.13 2014/11/28 18:57:31 schwarze Exp $ */ +/* $Id: att.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -19,6 +19,7 @@ #include <sys/types.h> #include <string.h> +#include "roff.h" #include "mdoc.h" #include "libmdoc.h" @@ -45,5 +46,5 @@ mdoc_a2att(const char *p) LINE("V.3", "AT&T System\\~V Release\\~3 UNIX"); LINE("V.4", "AT&T System\\~V Release\\~4 UNIX"); - return(NULL); + return NULL; } diff --git a/usr/src/cmd/mandoc/chars.c b/usr/src/cmd/mandoc/chars.c index 6b5eba9537..c2cfaf8184 100644 --- a/usr/src/cmd/mandoc/chars.c +++ b/usr/src/cmd/mandoc/chars.c @@ -1,7 +1,7 @@ -/* $Id: chars.c,v 1.66 2015/02/17 20:37:16 schwarze Exp $ */ +/* $Id: chars.c,v 1.68 2015/10/13 22:59:54 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,90 +21,429 @@ #include <assert.h> #include <ctype.h> +#include <stddef.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include "mandoc.h" #include "mandoc_aux.h" +#include "mandoc_ohash.h" #include "libmandoc.h" -#define PRINT_HI 126 -#define PRINT_LO 32 - struct ln { - struct ln *next; - const char *code; + const char roffcode[16]; const char *ascii; int unicode; }; -#define LINES_MAX 332 - -#define CHAR(in, ch, code) \ - { NULL, (in), (ch), (code) }, - -#define CHAR_TBL_START static struct ln lines[LINES_MAX] = { -#define CHAR_TBL_END }; - -#include "chars.in" - -struct mchars { - struct ln **htab; +/* Special break control characters. */ +static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' }; +static const char ascii_break[2] = { ASCII_BREAK, '\0' }; + +static struct ln lines[] = { + + /* Spacing. */ + { " ", ascii_nbrsp, 0x00a0 }, + { "~", ascii_nbrsp, 0x00a0 }, + { "0", " ", 0x2002 }, + { "|", "", 0 }, + { "^", "", 0 }, + { "&", "", 0 }, + { "%", "", 0 }, + { ":", ascii_break, 0 }, + /* XXX The following three do not really belong here. */ + { "t", "", 0 }, + { "c", "", 0 }, + { "}", "", 0 }, + + /* Lines. */ + { "ba", "|", 0x007c }, + { "br", "|", 0x2502 }, + { "ul", "_", 0x005f }, + { "rn", "-", 0x203e }, + { "bb", "|", 0x00a6 }, + { "sl", "/", 0x002f }, + { "rs", "\\", 0x005c }, + + /* Text markers. */ + { "ci", "O", 0x25cb }, + { "bu", "+\bo", 0x2022 }, + { "dd", "|\b=", 0x2021 }, + { "dg", "|\b-", 0x2020 }, + { "lz", "<>", 0x25ca }, + { "sq", "[]", 0x25a1 }, + { "ps", "<par>", 0x00b6 }, + { "sc", "<sec>", 0x00a7 }, + { "lh", "<=", 0x261c }, + { "rh", "=>", 0x261e }, + { "at", "@", 0x0040 }, + { "sh", "#", 0x0023 }, + { "CR", "_|", 0x21b5 }, + { "OK", "\\/", 0x2713 }, + + /* Legal symbols. */ + { "co", "(C)", 0x00a9 }, + { "rg", "(R)", 0x00ae }, + { "tm", "tm", 0x2122 }, + + /* Punctuation. */ + { "em", "--", 0x2014 }, + { "en", "-", 0x2013 }, + { "hy", "-", 0x2010 }, + { "e", "\\", 0x005c }, + { ".", ".", 0x002e }, + { "r!", "!", 0x00a1 }, + { "r?", "?", 0x00bf }, + + /* Quotes. */ + { "Bq", ",,", 0x201e }, + { "bq", ",", 0x201a }, + { "lq", "\"", 0x201c }, + { "rq", "\"", 0x201d }, + { "Lq", "``", 0x201c }, + { "Rq", "''", 0x201d }, + { "oq", "`", 0x2018 }, + { "cq", "\'", 0x2019 }, + { "aq", "\'", 0x0027 }, + { "dq", "\"", 0x0022 }, + { "Fo", "<<", 0x00ab }, + { "Fc", ">>", 0x00bb }, + { "fo", "<", 0x2039 }, + { "fc", ">", 0x203a }, + + /* Brackets. */ + { "lB", "[", 0x005b }, + { "rB", "]", 0x005d }, + { "lC", "{", 0x007b }, + { "rC", "}", 0x007d }, + { "la", "<", 0x27e8 }, + { "ra", ">", 0x27e9 }, + { "bv", "|", 0x23aa }, + { "braceex", "|", 0x23aa }, + { "bracketlefttp", "|", 0x23a1 }, + { "bracketleftbt", "|", 0x23a3 }, + { "bracketleftex", "|", 0x23a2 }, + { "bracketrighttp", "|", 0x23a4 }, + { "bracketrightbt", "|", 0x23a6 }, + { "bracketrightex", "|", 0x23a5 }, + { "lt", ",-", 0x23a7 }, + { "bracelefttp", ",-", 0x23a7 }, + { "lk", "{", 0x23a8 }, + { "braceleftmid", "{", 0x23a8 }, + { "lb", "`-", 0x23a9 }, + { "braceleftbt", "`-", 0x23a9 }, + { "braceleftex", "|", 0x23aa }, + { "rt", "-.", 0x23ab }, + { "bracerighttp", "-.", 0x23ab }, + { "rk", "}", 0x23ac }, + { "bracerightmid", "}", 0x23ac }, + { "rb", "-\'", 0x23ad }, + { "bracerightbt", "-\'", 0x23ad }, + { "bracerightex", "|", 0x23aa }, + { "parenlefttp", "/", 0x239b }, + { "parenleftbt", "\\", 0x239d }, + { "parenleftex", "|", 0x239c }, + { "parenrighttp", "\\", 0x239e }, + { "parenrightbt", "/", 0x23a0 }, + { "parenrightex", "|", 0x239f }, + + /* Arrows and lines. */ + { "<-", "<-", 0x2190 }, + { "->", "->", 0x2192 }, + { "<>", "<->", 0x2194 }, + { "da", "|\bv", 0x2193 }, + { "ua", "|\b^", 0x2191 }, + { "va", "^v", 0x2195 }, + { "lA", "<=", 0x21d0 }, + { "rA", "=>", 0x21d2 }, + { "hA", "<=>", 0x21d4 }, + { "uA", "=\b^", 0x21d1 }, + { "dA", "=\bv", 0x21d3 }, + { "vA", "^=v", 0x21d5 }, + + /* Logic. */ + { "AN", "^", 0x2227 }, + { "OR", "v", 0x2228 }, + { "no", "~", 0x00ac }, + { "tno", "~", 0x00ac }, + { "te", "3", 0x2203 }, + { "fa", "-\bV", 0x2200 }, + { "st", "-)", 0x220b }, + { "tf", ".:.", 0x2234 }, + { "3d", ".:.", 0x2234 }, + { "or", "|", 0x007c }, + + /* Mathematicals. */ + { "pl", "+", 0x002b }, + { "mi", "-", 0x2212 }, + { "-", "-", 0x002d }, + { "-+", "-+", 0x2213 }, + { "+-", "+-", 0x00b1 }, + { "t+-", "+-", 0x00b1 }, + { "pc", ".", 0x00b7 }, + { "md", ".", 0x22c5 }, + { "mu", "x", 0x00d7 }, + { "tmu", "x", 0x00d7 }, + { "c*", "O\bx", 0x2297 }, + { "c+", "O\b+", 0x2295 }, + { "di", "-:-", 0x00f7 }, + { "tdi", "-:-", 0x00f7 }, + { "f/", "/", 0x2044 }, + { "**", "*", 0x2217 }, + { "<=", "<=", 0x2264 }, + { ">=", ">=", 0x2265 }, + { "<<", "<<", 0x226a }, + { ">>", ">>", 0x226b }, + { "eq", "=", 0x003d }, + { "!=", "!=", 0x2260 }, + { "==", "==", 0x2261 }, + { "ne", "!==", 0x2262 }, + { "ap", "~", 0x223c }, + { "|=", "-~", 0x2243 }, + { "=~", "=~", 0x2245 }, + { "~~", "~~", 0x2248 }, + { "~=", "~=", 0x2248 }, + { "pt", "oc", 0x221d }, + { "es", "{}", 0x2205 }, + { "mo", "E", 0x2208 }, + { "nm", "!E", 0x2209 }, + { "sb", "(=", 0x2282 }, + { "nb", "(!=", 0x2284 }, + { "sp", "=)", 0x2283 }, + { "nc", "!=)", 0x2285 }, + { "ib", "(=\b_", 0x2286 }, + { "ip", "=\b_)", 0x2287 }, + { "ca", "(^)", 0x2229 }, + { "cu", "U", 0x222a }, + { "/_", "_\b/", 0x2220 }, + { "pp", "_\b|", 0x22a5 }, + { "is", "'\b,\bI", 0x222b }, + { "integral", "'\b,\bI", 0x222b }, + { "sum", "E", 0x2211 }, + { "product", "TT", 0x220f }, + { "coproduct", "U", 0x2210 }, + { "gr", "V", 0x2207 }, + { "sr", "\\/", 0x221a }, + { "sqrt", "\\/", 0x221a }, + { "lc", "|~", 0x2308 }, + { "rc", "~|", 0x2309 }, + { "lf", "|_", 0x230a }, + { "rf", "_|", 0x230b }, + { "if", "oo", 0x221e }, + { "Ah", "N", 0x2135 }, + { "Im", "I", 0x2111 }, + { "Re", "R", 0x211c }, + { "pd", "a", 0x2202 }, + { "-h", "/h", 0x210f }, + { "12", "1/2", 0x00bd }, + { "14", "1/4", 0x00bc }, + { "34", "3/4", 0x00be }, + + /* Ligatures. */ + { "ff", "ff", 0xfb00 }, + { "fi", "fi", 0xfb01 }, + { "fl", "fl", 0xfb02 }, + { "Fi", "ffi", 0xfb03 }, + { "Fl", "ffl", 0xfb04 }, + { "AE", "AE", 0x00c6 }, + { "ae", "ae", 0x00e6 }, + { "OE", "OE", 0x0152 }, + { "oe", "oe", 0x0153 }, + { "ss", "ss", 0x00df }, + { "IJ", "IJ", 0x0132 }, + { "ij", "ij", 0x0133 }, + + /* Accents. */ + { "a\"", "\"", 0x02dd }, + { "a-", "-", 0x00af }, + { "a.", ".", 0x02d9 }, + { "a^", "^", 0x005e }, + { "aa", "\'", 0x00b4 }, + { "\'", "\'", 0x00b4 }, + { "ga", "`", 0x0060 }, + { "`", "`", 0x0060 }, + { "ab", "'\b`", 0x02d8 }, + { "ac", ",", 0x00b8 }, + { "ad", "\"", 0x00a8 }, + { "ah", "v", 0x02c7 }, + { "ao", "o", 0x02da }, + { "a~", "~", 0x007e }, + { "ho", ",", 0x02db }, + { "ha", "^", 0x005e }, + { "ti", "~", 0x007e }, + + /* Accented letters. */ + { "'A", "'\bA", 0x00c1 }, + { "'E", "'\bE", 0x00c9 }, + { "'I", "'\bI", 0x00cd }, + { "'O", "'\bO", 0x00d3 }, + { "'U", "'\bU", 0x00da }, + { "'a", "'\ba", 0x00e1 }, + { "'e", "'\be", 0x00e9 }, + { "'i", "'\bi", 0x00ed }, + { "'o", "'\bo", 0x00f3 }, + { "'u", "'\bu", 0x00fa }, + { "`A", "`\bA", 0x00c0 }, + { "`E", "`\bE", 0x00c8 }, + { "`I", "`\bI", 0x00cc }, + { "`O", "`\bO", 0x00d2 }, + { "`U", "`\bU", 0x00d9 }, + { "`a", "`\ba", 0x00e0 }, + { "`e", "`\be", 0x00e8 }, + { "`i", "`\bi", 0x00ec }, + { "`o", "`\bo", 0x00f2 }, + { "`u", "`\bu", 0x00f9 }, + { "~A", "~\bA", 0x00c3 }, + { "~N", "~\bN", 0x00d1 }, + { "~O", "~\bO", 0x00d5 }, + { "~a", "~\ba", 0x00e3 }, + { "~n", "~\bn", 0x00f1 }, + { "~o", "~\bo", 0x00f5 }, + { ":A", "\"\bA", 0x00c4 }, + { ":E", "\"\bE", 0x00cb }, + { ":I", "\"\bI", 0x00cf }, + { ":O", "\"\bO", 0x00d6 }, + { ":U", "\"\bU", 0x00dc }, + { ":a", "\"\ba", 0x00e4 }, + { ":e", "\"\be", 0x00eb }, + { ":i", "\"\bi", 0x00ef }, + { ":o", "\"\bo", 0x00f6 }, + { ":u", "\"\bu", 0x00fc }, + { ":y", "\"\by", 0x00ff }, + { "^A", "^\bA", 0x00c2 }, + { "^E", "^\bE", 0x00ca }, + { "^I", "^\bI", 0x00ce }, + { "^O", "^\bO", 0x00d4 }, + { "^U", "^\bU", 0x00db }, + { "^a", "^\ba", 0x00e2 }, + { "^e", "^\be", 0x00ea }, + { "^i", "^\bi", 0x00ee }, + { "^o", "^\bo", 0x00f4 }, + { "^u", "^\bu", 0x00fb }, + { ",C", ",\bC", 0x00c7 }, + { ",c", ",\bc", 0x00e7 }, + { "/L", "/\bL", 0x0141 }, + { "/l", "/\bl", 0x0142 }, + { "/O", "/\bO", 0x00d8 }, + { "/o", "/\bo", 0x00f8 }, + { "oA", "o\bA", 0x00c5 }, + { "oa", "o\ba", 0x00e5 }, + + /* Special letters. */ + { "-D", "-\bD", 0x00d0 }, + { "Sd", "d", 0x00f0 }, + { "TP", "Th", 0x00de }, + { "Tp", "th", 0x00fe }, + { ".i", "i", 0x0131 }, + { ".j", "j", 0x0237 }, + + /* Currency. */ + { "Do", "$", 0x0024 }, + { "ct", "/\bc", 0x00a2 }, + { "Eu", "EUR", 0x20ac }, + { "eu", "EUR", 0x20ac }, + { "Ye", "=\bY", 0x00a5 }, + { "Po", "GBP", 0x00a3 }, + { "Cs", "o\bx", 0x00a4 }, + { "Fn", ",\bf", 0x0192 }, + + /* Units. */ + { "de", "<deg>", 0x00b0 }, + { "%0", "%o", 0x2030 }, + { "fm", "\'", 0x2032 }, + { "sd", "''", 0x2033 }, + { "mc", ",\bu", 0x00b5 }, + + /* Greek characters. */ + { "*A", "A", 0x0391 }, + { "*B", "B", 0x0392 }, + { "*G", "G", 0x0393 }, + { "*D", "_\b/_\b\\", 0x0394 }, + { "*E", "E", 0x0395 }, + { "*Z", "Z", 0x0396 }, + { "*Y", "H", 0x0397 }, + { "*H", "-\bO", 0x0398 }, + { "*I", "I", 0x0399 }, + { "*K", "K", 0x039a }, + { "*L", "/\\", 0x039b }, + { "*M", "M", 0x039c }, + { "*N", "N", 0x039d }, + { "*C", "_\bH", 0x039e }, + { "*O", "O", 0x039f }, + { "*P", "TT", 0x03a0 }, + { "*R", "P", 0x03a1 }, + { "*S", "S", 0x03a3 }, + { "*T", "T", 0x03a4 }, + { "*U", "Y", 0x03a5 }, + { "*F", "I\bO", 0x03a6 }, + { "*X", "X", 0x03a7 }, + { "*Q", "I\bY", 0x03a8 }, + { "*W", "_\bO", 0x03a9 }, + { "*a", "a", 0x03b1 }, + { "*b", "B", 0x03b2 }, + { "*g", "y", 0x03b3 }, + { "*d", "d", 0x03b4 }, + { "*e", "e", 0x03b5 }, + { "*z", ",\bC", 0x03b6 }, + { "*y", "n", 0x03b7 }, + { "*h", "-\b0", 0x03b8 }, + { "*i", "i", 0x03b9 }, + { "*k", "k", 0x03ba }, + { "*l", ">\b\\", 0x03bb }, + { "*m", ",\bu", 0x03bc }, + { "*n", "v", 0x03bd }, + { "*c", ",\bE", 0x03be }, + { "*o", "o", 0x03bf }, + { "*p", "-\bn", 0x03c0 }, + { "*r", "p", 0x03c1 }, + { "*s", "-\bo", 0x03c3 }, + { "*t", "~\bt", 0x03c4 }, + { "*u", "u", 0x03c5 }, + { "*f", "|\bo", 0x03d5 }, + { "*x", "x", 0x03c7 }, + { "*q", "|\bu", 0x03c8 }, + { "*w", "w", 0x03c9 }, + { "+h", "-\b0", 0x03d1 }, + { "+f", "|\bo", 0x03c6 }, + { "+p", "-\bw", 0x03d6 }, + { "+e", "e", 0x03f5 }, + { "ts", "s", 0x03c2 }, }; -static const struct ln *find(const struct mchars *, - const char *, size_t); +static struct ohash mchars; void -mchars_free(struct mchars *arg) +mchars_free(void) { - free(arg->htab); - free(arg); + ohash_delete(&mchars); } -struct mchars * +void mchars_alloc(void) { - struct mchars *tab; - struct ln **htab; - struct ln *pp; - int i, hash; - - /* - * Constructs a very basic chaining hashtable. The hash routine - * is simply the integral value of the first character. - * Subsequent entries are chained in the order they're processed. - */ - - tab = mandoc_malloc(sizeof(struct mchars)); - htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln *)); - - for (i = 0; i < LINES_MAX; i++) { - hash = (int)lines[i].code[0] - PRINT_LO; - - if (NULL == (pp = htab[hash])) { - htab[hash] = &lines[i]; - continue; - } - - for ( ; pp->next; pp = pp->next) - /* Scan ahead. */ ; - pp->next = &lines[i]; + size_t i; + unsigned int slot; + + mandoc_ohash_init(&mchars, 9, offsetof(struct ln, roffcode)); + for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++) { + slot = ohash_qlookup(&mchars, lines[i].roffcode); + assert(ohash_find(&mchars, slot) == NULL); + ohash_insert(&mchars, slot, lines + i); } - - tab->htab = htab; - return(tab); } int -mchars_spec2cp(const struct mchars *arg, const char *p, size_t sz) +mchars_spec2cp(const char *p, size_t sz) { const struct ln *ln; + const char *end; - ln = find(arg, p, sz); - return(ln != NULL ? ln->unicode : sz == 1 ? (unsigned char)*p : -1); + end = p + sz; + ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end)); + return ln != NULL ? ln->unicode : sz == 1 ? (unsigned char)*p : -1; } int @@ -113,7 +452,7 @@ mchars_num2char(const char *p, size_t sz) int i; i = mandoc_strntoi(p, sz, 10); - return(i >= 0 && i < 256 ? i : -1); + return i >= 0 && i < 256 ? i : -1; } int @@ -123,53 +462,33 @@ mchars_num2uc(const char *p, size_t sz) i = mandoc_strntoi(p, sz, 16); assert(i >= 0 && i <= 0x10FFFF); - return(i); + return i; } const char * -mchars_spec2str(const struct mchars *arg, - const char *p, size_t sz, size_t *rsz) +mchars_spec2str(const char *p, size_t sz, size_t *rsz) { const struct ln *ln; + const char *end; - ln = find(arg, p, sz); + end = p + sz; + ln = ohash_find(&mchars, ohash_qlookupi(&mchars, p, &end)); if (ln == NULL) { *rsz = 1; - return(sz == 1 ? p : NULL); + return sz == 1 ? p : NULL; } *rsz = strlen(ln->ascii); - return(ln->ascii); + return ln->ascii; } const char * mchars_uc2str(int uc) { - int i; + size_t i; - for (i = 0; i < LINES_MAX; i++) + for (i = 0; i < sizeof(lines)/sizeof(lines[0]); i++) if (uc == lines[i].unicode) - return(lines[i].ascii); - return("<?>"); -} - -static const struct ln * -find(const struct mchars *tab, const char *p, size_t sz) -{ - const struct ln *pp; - int hash; - - assert(p); - - if (0 == sz || p[0] < PRINT_LO || p[0] > PRINT_HI) - return(NULL); - - hash = (int)p[0] - PRINT_LO; - - for (pp = tab->htab[hash]; pp; pp = pp->next) - if (0 == strncmp(pp->code, p, sz) && - '\0' == pp->code[(int)sz]) - return(pp); - - return(NULL); + return lines[i].ascii; + return "<?>"; } diff --git a/usr/src/cmd/mandoc/chars.in b/usr/src/cmd/mandoc/chars.in deleted file mode 100644 index ac72aba858..0000000000 --- a/usr/src/cmd/mandoc/chars.in +++ /dev/null @@ -1,404 +0,0 @@ -/* $Id: chars.in,v 1.52 2015/02/17 20:37:16 schwarze Exp $ */ -/* - * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * The ASCII translation tables. - * - * The left-hand side corresponds to the input sequence (\x, \(xx, \*(xx - * and so on) whose length is listed second element. The right-hand - * side is what's produced by the front-end, with the fourth element - * being its length. - * - * XXX - C-escape strings! - * XXX - update LINES_MAX if adding more! - */ - -/* Special break control characters. */ -static const char ascii_nbrsp[2] = { ASCII_NBRSP, '\0' }; -static const char ascii_break[2] = { ASCII_BREAK, '\0' }; - -CHAR_TBL_START - -/* Spacing. */ -CHAR(" ", ascii_nbrsp, 160) -CHAR("~", ascii_nbrsp, 160) -CHAR("0", " ", 8194) -CHAR("|", "", 0) -CHAR("^", "", 0) -CHAR("&", "", 0) -CHAR("%", "", 0) -CHAR(":", ascii_break, 0) -/* XXX The following three do not really belong into this file. */ -CHAR("t", "", 0) -CHAR("c", "", 0) -CHAR("}", "", 0) - -/* Accents. */ -CHAR("a\"", "\"", 733) -CHAR("a-", "-", 175) -CHAR("a.", ".", 729) -CHAR("a^", "^", 94) -CHAR("\'", "\'", 180) -CHAR("aa", "\'", 180) -CHAR("ga", "`", 96) -CHAR("`", "`", 96) -CHAR("ab", "'\b`", 728) -CHAR("ac", ",", 184) -CHAR("ad", "\"", 168) -CHAR("ah", "v", 711) -CHAR("ao", "o", 730) -CHAR("a~", "~", 126) -CHAR("ho", ",", 731) -CHAR("ha", "^", 94) -CHAR("ti", "~", 126) - -/* Quotes. */ -CHAR("Bq", ",,", 8222) -CHAR("bq", ",", 8218) -CHAR("lq", "\"", 8220) -CHAR("rq", "\"", 8221) -CHAR("Lq", "``", 8220) -CHAR("Rq", "''", 8221) -CHAR("oq", "`", 8216) -CHAR("cq", "\'", 8217) -CHAR("aq", "\'", 39) -CHAR("dq", "\"", 34) -CHAR("Fo", "<<", 171) -CHAR("Fc", ">>", 187) -CHAR("fo", "<", 8249) -CHAR("fc", ">", 8250) - -/* Brackets. */ -CHAR("lB", "[", 91) -CHAR("rB", "]", 93) -CHAR("lC", "{", 123) -CHAR("rC", "}", 125) -CHAR("la", "<", 10216) -CHAR("ra", ">", 10217) -CHAR("bv", "|", 9130) -CHAR("braceex", "|", 9130) -CHAR("bracketlefttp", "|", 9121) -CHAR("bracketleftbt", "|", 9123) -CHAR("bracketleftex", "|", 9122) -CHAR("bracketrighttp", "|", 9124) -CHAR("bracketrightbt", "|", 9126) -CHAR("bracketrightex", "|", 9125) -CHAR("lt", ",-", 9127) -CHAR("bracelefttp", ",-", 9127) -CHAR("lk", "{", 9128) -CHAR("braceleftmid", "{", 9128) -CHAR("lb", "`-", 9129) -CHAR("braceleftbt", "`-", 9129) -CHAR("braceleftex", "|", 9130) -CHAR("rt", "-.", 9131) -CHAR("bracerighttp", "-.", 9131) -CHAR("rk", "}", 9132) -CHAR("bracerightmid", "}", 9132) -CHAR("rb", "-\'", 9133) -CHAR("bracerightbt", "-\'", 9133) -CHAR("bracerightex", "|", 9130) -CHAR("parenlefttp", "/", 9115) -CHAR("parenleftbt", "\\", 9117) -CHAR("parenleftex", "|", 9116) -CHAR("parenrighttp", "\\", 9118) -CHAR("parenrightbt", "/", 9120) -CHAR("parenrightex", "|", 9119) - -/* Greek characters. */ -CHAR("*A", "A", 913) -CHAR("*B", "B", 914) -CHAR("*G", "G", 915) -CHAR("*D", "_\b/_\b\\", 916) -CHAR("*E", "E", 917) -CHAR("*Z", "Z", 918) -CHAR("*Y", "H", 919) -CHAR("*H", "-\bO", 920) -CHAR("*I", "I", 921) -CHAR("*K", "K", 922) -CHAR("*L", "/\\", 923) -CHAR("*M", "M", 924) -CHAR("*N", "N", 925) -CHAR("*C", "_\bH", 926) -CHAR("*O", "O", 927) -CHAR("*P", "TT", 928) -CHAR("*R", "P", 929) -CHAR("*S", "S", 931) -CHAR("*T", "T", 932) -CHAR("*U", "Y", 933) -CHAR("*F", "I\bO", 934) -CHAR("*X", "X", 935) -CHAR("*Q", "I\bY", 936) -CHAR("*W", "_\bO", 937) -CHAR("*a", "a", 945) -CHAR("*b", "B", 946) -CHAR("*g", "y", 947) -CHAR("*d", "d", 948) -CHAR("*e", "e", 949) -CHAR("*z", ",\bC", 950) -CHAR("*y", "n", 951) -CHAR("*h", "-\b0", 952) -CHAR("*i", "i", 953) -CHAR("*k", "k", 954) -CHAR("*l", ">\b\\", 955) -CHAR("*m", ",\bu", 956) -CHAR("*n", "v", 957) -CHAR("*c", ",\bE", 958) -CHAR("*o", "o", 959) -CHAR("*p", "-\bn", 960) -CHAR("*r", "p", 961) -CHAR("*s", "-\bo", 963) -CHAR("*t", "~\bt", 964) -CHAR("*u", "u", 965) -CHAR("*f", "|\bo", 981) -CHAR("*x", "x", 967) -CHAR("*q", "|\bu", 968) -CHAR("*w", "w", 969) -CHAR("+h", "-\b0", 977) -CHAR("+f", "|\bo", 966) -CHAR("+p", "-\bw", 982) -CHAR("+e", "e", 1013) -CHAR("ts", "s", 962) - -/* Accented letters. */ -CHAR(",C", ",\bC", 199) -CHAR(",c", ",\bc", 231) -CHAR("/L", "/\bL", 321) -CHAR("/O", "/\bO", 216) -CHAR("/l", "/\bl", 322) -CHAR("/o", "/\bo", 248) -CHAR("oA", "o\bA", 197) -CHAR("oa", "o\ba", 229) -CHAR(":A", "\"\bA", 196) -CHAR(":E", "\"\bE", 203) -CHAR(":I", "\"\bI", 207) -CHAR(":O", "\"\bO", 214) -CHAR(":U", "\"\bU", 220) -CHAR(":a", "\"\ba", 228) -CHAR(":e", "\"\be", 235) -CHAR(":i", "\"\bi", 239) -CHAR(":o", "\"\bo", 246) -CHAR(":u", "\"\bu", 252) -CHAR(":y", "\"\by", 255) -CHAR("'A", "'\bA", 193) -CHAR("'E", "'\bE", 201) -CHAR("'I", "'\bI", 205) -CHAR("'O", "'\bO", 211) -CHAR("'U", "'\bU", 218) -CHAR("'a", "'\ba", 225) -CHAR("'e", "'\be", 233) -CHAR("'i", "'\bi", 237) -CHAR("'o", "'\bo", 243) -CHAR("'u", "'\bu", 250) -CHAR("^A", "^\bA", 194) -CHAR("^E", "^\bE", 202) -CHAR("^I", "^\bI", 206) -CHAR("^O", "^\bO", 212) -CHAR("^U", "^\bU", 219) -CHAR("^a", "^\ba", 226) -CHAR("^e", "^\be", 234) -CHAR("^i", "^\bi", 238) -CHAR("^o", "^\bo", 244) -CHAR("^u", "^\bu", 251) -CHAR("`A", "`\bA", 192) -CHAR("`E", "`\bE", 200) -CHAR("`I", "`\bI", 204) -CHAR("`O", "`\bO", 210) -CHAR("`U", "`\bU", 217) -CHAR("`a", "`\ba", 224) -CHAR("`e", "`\be", 232) -CHAR("`i", "`\bi", 236) -CHAR("`o", "`\bo", 242) -CHAR("`u", "`\bu", 249) -CHAR("~A", "~\bA", 195) -CHAR("~N", "~\bN", 209) -CHAR("~O", "~\bO", 213) -CHAR("~a", "~\ba", 227) -CHAR("~n", "~\bn", 241) -CHAR("~o", "~\bo", 245) - -/* Arrows and lines. */ -CHAR("<-", "<-", 8592) -CHAR("->", "->", 8594) -CHAR("<>", "<->", 8596) -CHAR("da", "|\bv", 8595) -CHAR("ua", "|\b^", 8593) -CHAR("va", "^v", 8597) -CHAR("lA", "<=", 8656) -CHAR("rA", "=>", 8658) -CHAR("hA", "<=>", 8660) -CHAR("dA", "=\bv", 8659) -CHAR("uA", "=\b^", 8657) -CHAR("vA", "^=v", 8661) - -/* Logic. */ -CHAR("AN", "^", 8743) -CHAR("OR", "v", 8744) -CHAR("no", "~", 172) -CHAR("tno", "~", 172) -CHAR("te", "3", 8707) -CHAR("fa", "-\bV", 8704) -CHAR("st", "-)", 8715) -CHAR("tf", ".:.", 8756) -CHAR("3d", ".:.", 8756) -CHAR("or", "|", 124) - -/* Mathematicals. */ -CHAR("pl", "+", 43) -CHAR("mi", "-", 8722) -CHAR("-", "-", 45) -CHAR("-+", "-+", 8723) -CHAR("+-", "+-", 177) -CHAR("t+-", "+-", 177) -CHAR("pc", ".", 183) -CHAR("md", ".", 8901) -CHAR("mu", "x", 215) -CHAR("tmu", "x", 215) -CHAR("c*", "O\bx", 8855) -CHAR("c+", "O\b+", 8853) -CHAR("di", "-:-", 247) -CHAR("tdi", "-:-", 247) -CHAR("f/", "/", 8260) -CHAR("**", "*", 8727) -CHAR("<=", "<=", 8804) -CHAR(">=", ">=", 8805) -CHAR("<<", "<<", 8810) -CHAR(">>", ">>", 8811) -CHAR("eq", "=", 61) -CHAR("!=", "!=", 8800) -CHAR("==", "==", 8801) -CHAR("ne", "!==", 8802) -CHAR("=~", "=~", 8773) -CHAR("|=", "-~", 8771) -CHAR("ap", "~", 8764) -CHAR("~~", "~~", 8776) -CHAR("~=", "~=", 8776) -CHAR("pt", "oc", 8733) -CHAR("es", "{}", 8709) -CHAR("mo", "E", 8712) -CHAR("nm", "!E", 8713) -CHAR("sb", "(=", 8834) -CHAR("nb", "(!=", 8836) -CHAR("sp", "=)", 8835) -CHAR("nc", "!=)", 8837) -CHAR("ib", "(=\b_", 8838) -CHAR("ip", "=\b_)", 8839) -CHAR("ca", "(^)", 8745) -CHAR("cu", "U", 8746) -CHAR("/_", "_\b/", 8736) -CHAR("pp", "_\b|", 8869) -CHAR("is", "'\b,\bI", 8747) -CHAR("integral", "'\b,\bI", 8747) -CHAR("sum", "E", 8721) -CHAR("product", "TT", 8719) -CHAR("coproduct", "U", 8720) -CHAR("gr", "V", 8711) -CHAR("sr", "\\/", 8730) -CHAR("sqrt", "\\/", 8730) -CHAR("lc", "|~", 8968) -CHAR("rc", "~|", 8969) -CHAR("lf", "|_", 8970) -CHAR("rf", "_|", 8971) -CHAR("if", "oo", 8734) -CHAR("Ah", "N", 8501) -CHAR("Im", "I", 8465) -CHAR("Re", "R", 8476) -CHAR("pd", "a", 8706) -CHAR("-h", "/h", 8463) -CHAR("12", "1/2", 189) -CHAR("14", "1/4", 188) -CHAR("34", "3/4", 190) - -/* Ligatures. */ -CHAR("ff", "ff", 64256) -CHAR("fi", "fi", 64257) -CHAR("fl", "fl", 64258) -CHAR("Fi", "ffi", 64259) -CHAR("Fl", "ffl", 64260) -CHAR("AE", "AE", 198) -CHAR("ae", "ae", 230) -CHAR("OE", "OE", 338) -CHAR("oe", "oe", 339) -CHAR("ss", "ss", 223) -CHAR("IJ", "IJ", 306) -CHAR("ij", "ij", 307) - -/* Special letters. */ -CHAR("-D", "-\bD", 208) -CHAR("Sd", "d", 240) -CHAR("TP", "Th", 222) -CHAR("Tp", "th", 254) -CHAR(".i", "i", 305) -CHAR(".j", "j", 567) - -/* Currency. */ -CHAR("Do", "$", 36) -CHAR("ct", "/\bc", 162) -CHAR("Eu", "EUR", 8364) -CHAR("eu", "EUR", 8364) -CHAR("Ye", "=\bY", 165) -CHAR("Po", "GBP", 163) -CHAR("Cs", "o\bx", 164) -CHAR("Fn", ",\bf", 402) - -/* Lines. */ -CHAR("ba", "|", 124) -CHAR("br", "|", 9474) -CHAR("ul", "_", 95) -CHAR("rn", "-", 8254) -CHAR("bb", "|", 166) -CHAR("sl", "/", 47) -CHAR("rs", "\\", 92) - -/* Text markers. */ -CHAR("ci", "O", 9675) -CHAR("bu", "+\bo", 8226) -CHAR("dd", "|\b=", 8225) -CHAR("dg", "|\b-", 8224) -CHAR("lz", "<>", 9674) -CHAR("sq", "[]", 9633) -CHAR("ps", "<par>", 182) -CHAR("sc", "<sec>", 167) -CHAR("lh", "<=", 9756) -CHAR("rh", "=>", 9758) -CHAR("at", "@", 64) -CHAR("sh", "#", 35) -CHAR("CR", "_|", 8629) -CHAR("OK", "\\/", 10003) - -/* Legal symbols. */ -CHAR("co", "(C)", 169) -CHAR("rg", "(R)", 174) -CHAR("tm", "tm", 8482) - -/* Punctuation. */ -CHAR(".", ".", 46) -CHAR("r!", "!", 161) -CHAR("r?", "?", 191) -CHAR("em", "--", 8212) -CHAR("en", "-", 8211) -CHAR("hy", "-", 8208) -CHAR("e", "\\", 92) - -/* Units. */ -CHAR("de", "<deg>", 176) -CHAR("%0", "%o", 8240) -CHAR("fm", "\'", 8242) -CHAR("sd", "''", 8243) -CHAR("mc", ",\bu", 181) - -CHAR_TBL_END diff --git a/usr/src/cmd/mandoc/compat_fgetln.c b/usr/src/cmd/mandoc/compat_fgetln.c deleted file mode 100644 index 3760ab994d..0000000000 --- a/usr/src/cmd/mandoc/compat_fgetln.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "config.h" - -#if HAVE_FGETLN - -int dummy; - -#else - -/* $NetBSD: fgetln.c,v 1.3 2006/09/25 07:18:17 lukem Exp $ */ - -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Christos Zoulas. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -char * -fgetln(fp, len) - FILE *fp; - size_t *len; -{ - static char *buf = NULL; - static size_t bufsiz = 0; - char *ptr; - - - if (buf == NULL) { - bufsiz = BUFSIZ; - if ((buf = malloc(bufsiz)) == NULL) - return NULL; - } - - if (fgets(buf, bufsiz, fp) == NULL) - return NULL; - - *len = 0; - while ((ptr = strchr(&buf[*len], '\n')) == NULL) { - size_t nbufsiz = bufsiz + BUFSIZ; - char *nbuf = realloc(buf, nbufsiz); - - if (nbuf == NULL) { - int oerrno = errno; - free(buf); - errno = oerrno; - buf = NULL; - return NULL; - } else - buf = nbuf; - - *len = bufsiz; - if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) - return buf; - - bufsiz = nbufsiz; - } - - *len = (ptr - buf) + 1; - return buf; -} - -#endif diff --git a/usr/src/cmd/mandoc/compat_ohash.c b/usr/src/cmd/mandoc/compat_ohash.c new file mode 100644 index 0000000000..cbd6052182 --- /dev/null +++ b/usr/src/cmd/mandoc/compat_ohash.c @@ -0,0 +1,339 @@ +#include "config.h" + +#if HAVE_OHASH + +int dummy; + +#else + +/* $OpenBSD: ohash.c,v 1.1 2014/06/02 18:52:03 deraadt Exp $ */ + +/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include "compat_ohash.h" + +struct _ohash_record { + uint32_t hv; + const char *p; +}; + +#define DELETED ((const char *)h) +#define NONE (h->size) + +/* Don't bother changing the hash table if the change is small enough. */ +#define MINSIZE (1UL << 4) +#define MINDELETED 4 + +static void ohash_resize(struct ohash *); + + +/* This handles the common case of variable length keys, where the + * key is stored at the end of the record. + */ +void * +ohash_create_entry(struct ohash_info *i, const char *start, const char **end) +{ + char *p; + + if (!*end) + *end = start + strlen(start); + p = (i->alloc)(i->key_offset + (*end - start) + 1, i->data); + if (p) { + memcpy(p+i->key_offset, start, *end-start); + p[i->key_offset + (*end - start)] = '\0'; + } + return (void *)p; +} + +/* hash_delete only frees the hash structure. Use hash_first/hash_next + * to free entries as well. */ +void +ohash_delete(struct ohash *h) +{ + (h->info.free)(h->t, h->info.data); +#ifndef NDEBUG + h->t = NULL; +#endif +} + +static void +ohash_resize(struct ohash *h) +{ + struct _ohash_record *n; + size_t ns; + unsigned int j; + unsigned int i, incr; + + if (4 * h->deleted < h->total) { + if (h->size >= (UINT_MAX >> 1U)) + ns = UINT_MAX; + else + ns = h->size << 1U; + } else if (3 * h->deleted > 2 * h->total) + ns = h->size >> 1U; + else + ns = h->size; + if (ns < MINSIZE) + ns = MINSIZE; +#ifdef STATS_HASH + STAT_HASH_EXPAND++; + STAT_HASH_SIZE += ns - h->size; +#endif + + n = (h->info.calloc)(ns, sizeof(struct _ohash_record), h->info.data); + if (!n) + return; + + for (j = 0; j < h->size; j++) { + if (h->t[j].p != NULL && h->t[j].p != DELETED) { + i = h->t[j].hv % ns; + incr = ((h->t[j].hv % (ns - 2)) & ~1) + 1; + while (n[i].p != NULL) { + i += incr; + if (i >= ns) + i -= ns; + } + n[i].hv = h->t[j].hv; + n[i].p = h->t[j].p; + } + } + (h->info.free)(h->t, h->info.data); + h->t = n; + h->size = ns; + h->total -= h->deleted; + h->deleted = 0; +} + +void * +ohash_remove(struct ohash *h, unsigned int i) +{ + void *result = (void *)h->t[i].p; + + if (result == NULL || result == DELETED) + return NULL; + +#ifdef STATS_HASH + STAT_HASH_ENTRIES--; +#endif + h->t[i].p = DELETED; + h->deleted++; + if (h->deleted >= MINDELETED && 4 * h->deleted > h->total) + ohash_resize(h); + return result; +} + +void * +ohash_find(struct ohash *h, unsigned int i) +{ + if (h->t[i].p == DELETED) + return NULL; + else + return (void *)h->t[i].p; +} + +void * +ohash_insert(struct ohash *h, unsigned int i, void *p) +{ +#ifdef STATS_HASH + STAT_HASH_ENTRIES++; +#endif + if (h->t[i].p == DELETED) { + h->deleted--; + h->t[i].p = p; + } else { + h->t[i].p = p; + /* Arbitrary resize boundary. Tweak if not efficient enough. */ + if (++h->total * 4 > h->size * 3) + ohash_resize(h); + } + return p; +} + +unsigned int +ohash_entries(struct ohash *h) +{ + return h->total - h->deleted; +} + +void * +ohash_first(struct ohash *h, unsigned int *pos) +{ + *pos = 0; + return ohash_next(h, pos); +} + +void * +ohash_next(struct ohash *h, unsigned int *pos) +{ + for (; *pos < h->size; (*pos)++) + if (h->t[*pos].p != DELETED && h->t[*pos].p != NULL) + return (void *)h->t[(*pos)++].p; + return NULL; +} + +void +ohash_init(struct ohash *h, unsigned int size, struct ohash_info *info) +{ + h->size = 1UL << size; + if (h->size < MINSIZE) + h->size = MINSIZE; +#ifdef STATS_HASH + STAT_HASH_CREATION++; + STAT_HASH_SIZE += h->size; +#endif + /* Copy info so that caller may free it. */ + h->info.key_offset = info->key_offset; + h->info.calloc = info->calloc; + h->info.free = info->free; + h->info.alloc = info->alloc; + h->info.data = info->data; + h->t = (h->info.calloc)(h->size, sizeof(struct _ohash_record), + h->info.data); + h->total = h->deleted = 0; +} + +uint32_t +ohash_interval(const char *s, const char **e) +{ + uint32_t k; + + if (!*e) + *e = s + strlen(s); + if (s == *e) + k = 0; + else + k = *s++; + while (s != *e) + k = ((k << 2) | (k >> 30)) ^ *s++; + return k; +} + +unsigned int +ohash_lookup_interval(struct ohash *h, const char *start, const char *end, + uint32_t hv) +{ + unsigned int i, incr; + unsigned int empty; + +#ifdef STATS_HASH + STAT_HASH_LOOKUP++; +#endif + empty = NONE; + i = hv % h->size; + incr = ((hv % (h->size-2)) & ~1) + 1; + while (h->t[i].p != NULL) { +#ifdef STATS_HASH + STAT_HASH_LENGTH++; +#endif + if (h->t[i].p == DELETED) { + if (empty == NONE) + empty = i; + } else if (h->t[i].hv == hv && + strncmp(h->t[i].p+h->info.key_offset, start, + end - start) == 0 && + (h->t[i].p+h->info.key_offset)[end-start] == '\0') { + if (empty != NONE) { + h->t[empty].hv = hv; + h->t[empty].p = h->t[i].p; + h->t[i].p = DELETED; + return empty; + } else { +#ifdef STATS_HASH + STAT_HASH_POSITIVE++; +#endif + return i; + } + } + i += incr; + if (i >= h->size) + i -= h->size; + } + + /* Found an empty position. */ + if (empty != NONE) + i = empty; + h->t[i].hv = hv; + return i; +} + +unsigned int +ohash_lookup_memory(struct ohash *h, const char *k, size_t size, uint32_t hv) +{ + unsigned int i, incr; + unsigned int empty; + +#ifdef STATS_HASH + STAT_HASH_LOOKUP++; +#endif + empty = NONE; + i = hv % h->size; + incr = ((hv % (h->size-2)) & ~1) + 1; + while (h->t[i].p != NULL) { +#ifdef STATS_HASH + STAT_HASH_LENGTH++; +#endif + if (h->t[i].p == DELETED) { + if (empty == NONE) + empty = i; + } else if (h->t[i].hv == hv && + memcmp(h->t[i].p+h->info.key_offset, k, size) == 0) { + if (empty != NONE) { + h->t[empty].hv = hv; + h->t[empty].p = h->t[i].p; + h->t[i].p = DELETED; + return empty; + } else { +#ifdef STATS_HASH + STAT_HASH_POSITIVE++; +#endif + } return i; + } + i += incr; + if (i >= h->size) + i -= h->size; + } + + /* Found an empty position. */ + if (empty != NONE) + i = empty; + h->t[i].hv = hv; + return i; +} + +unsigned int +ohash_qlookup(struct ohash *h, const char *s) +{ + const char *e = NULL; + return ohash_qlookupi(h, s, &e); +} + +unsigned int +ohash_qlookupi(struct ohash *h, const char *s, const char **e) +{ + uint32_t hv; + + hv = ohash_interval(s, e); + return ohash_lookup_interval(h, s, *e, hv); +} + +#endif /*!HAVE_OHASH*/ diff --git a/usr/src/cmd/mandoc/compat_ohash.h b/usr/src/cmd/mandoc/compat_ohash.h new file mode 100644 index 0000000000..58fb220c96 --- /dev/null +++ b/usr/src/cmd/mandoc/compat_ohash.h @@ -0,0 +1,72 @@ +/* $OpenBSD: ohash.h,v 1.2 2014/06/02 18:52:03 deraadt Exp $ */ + +/* Copyright (c) 1999, 2004 Marc Espie <espie@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef OHASH_H +#define OHASH_H + +/* Open hashing support. + * Open hashing was chosen because it is much lighter than other hash + * techniques, and more efficient in most cases. + */ + +/* user-visible data structure */ +struct ohash_info { + ptrdiff_t key_offset; + void *data; /* user data */ + void *(*calloc)(size_t, size_t, void *); + void (*free)(void *, void *); + void *(*alloc)(size_t, void *); +}; + +struct _ohash_record; + +/* private structure. It's there just so you can do a sizeof */ +struct ohash { + struct _ohash_record *t; + struct ohash_info info; + unsigned int size; + unsigned int total; + unsigned int deleted; +}; + +/* For this to be tweakable, we use small primitives, and leave part of the + * logic to the client application. e.g., hashing is left to the client + * application. We also provide a simple table entry lookup that yields + * a hashing table index (opaque) to be used in find/insert/remove. + * The keys are stored at a known position in the client data. + */ +void ohash_init(struct ohash *, unsigned, struct ohash_info *); +void ohash_delete(struct ohash *); + +unsigned int ohash_lookup_interval(struct ohash *, const char *, + const char *, uint32_t); +unsigned int ohash_lookup_memory(struct ohash *, const char *, + size_t, uint32_t); +void *ohash_find(struct ohash *, unsigned int); +void *ohash_remove(struct ohash *, unsigned int); +void *ohash_insert(struct ohash *, unsigned int, void *); +void *ohash_first(struct ohash *, unsigned int *); +void *ohash_next(struct ohash *, unsigned int *); +unsigned int ohash_entries(struct ohash *); + +void *ohash_create_entry(struct ohash_info *, const char *, const char **); +uint32_t ohash_interval(const char *, const char **); + +unsigned int ohash_qlookupi(struct ohash *, const char *, const char **); +unsigned int ohash_qlookup(struct ohash *, const char *); + +#endif diff --git a/usr/src/cmd/mandoc/config.h b/usr/src/cmd/mandoc/config.h index 040fc56e39..a9106ae4f4 100644 --- a/usr/src/cmd/mandoc/config.h +++ b/usr/src/cmd/mandoc/config.h @@ -1,58 +1,28 @@ #ifndef MANDOC_CONFIG_H #define MANDOC_CONFIG_H -#if defined(__linux__) || defined(__MINT__) -#define _GNU_SOURCE /* See test-*.c what needs this. */ -#endif - #include <sys/types.h> #include <stdio.h> -#define HAVE_DIRENT_NAMLEN 0 -#define HAVE_FGETLN 0 -#define HAVE_FTS 0 -#define HAVE_GETSUBOPT 1 +#define HAVE_ERR 1 +#define HAVE_MANPATH 1 #define HAVE_MMAP 1 +#define HAVE_OHASH 0 +#define HAVE_PLEDGE 0 +#define HAVE_PROGNAME 1 #define HAVE_REALLOCARRAY 0 -#define HAVE_STRCASESTR 1 -#define HAVE_STRLCAT 1 -#define HAVE_STRLCPY 1 +#define HAVE_SANDBOX_INIT 0 +#define HAVE_SQLITE3 0 #define HAVE_STRPTIME 1 -#define HAVE_STRSEP 1 #define HAVE_STRTONUM 0 #define HAVE_WCHAR 1 -#define HAVE_SQLITE3 0 -#define HAVE_SQLITE3_ERRSTR 1 -#define HAVE_OHASH 1 -#define HAVE_MANPATH 0 #define BINM_APROPOS "apropos" #define BINM_MAN "man" #define BINM_WHATIS "whatis" -#define BINM_MAKEWHATIS "makewhatis" - -#if !defined(__BEGIN_DECLS) -# ifdef __cplusplus -# define __BEGIN_DECLS extern "C" { -# else -# define __BEGIN_DECLS -# endif -#endif -#if !defined(__END_DECLS) -# ifdef __cplusplus -# define __END_DECLS } -# else -# define __END_DECLS -# endif -#endif +#define BINM_MAKEWHATIS "man -w" -extern char *fgetln(FILE *, size_t *); -extern int getsubopt(char **, char * const *, char **); extern void *reallocarray(void *, size_t, size_t); -extern char *strcasestr(const char *, const char *); -extern size_t strlcat(char *, const char *, size_t); -extern size_t strlcpy(char *, const char *, size_t); -extern char *strsep(char **, const char *); extern long long strtonum(const char *, long long, long long, const char **); #endif /* MANDOC_CONFIG_H */ diff --git a/usr/src/cmd/mandoc/eqn.c b/usr/src/cmd/mandoc/eqn.c index 9da57f06e2..e9fbdec086 100644 --- a/usr/src/cmd/mandoc/eqn.c +++ b/usr/src/cmd/mandoc/eqn.c @@ -1,4 +1,4 @@ -/* $Id: eqn.c,v 1.58 2015/03/04 12:19:49 schwarze Exp $ */ +/* $Id: eqn.c,v 1.61 2016/01/08 00:50:45 schwarze Exp $ */ /* * Copyright (c) 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -302,10 +302,10 @@ eqn_read(struct eqn_node **epp, int ln, while (' ' == *p || '\t' == *p) p++; if ('\0' == *p) - return(er); + return er; mandoc_vmsg(MANDOCERR_ARG_SKIP, ep->parse, ln, pos, "EN %s", p); - return(er); + return er; } /* @@ -324,7 +324,7 @@ eqn_read(struct eqn_node **epp, int ln, ep->sz += sz; strlcat(ep->data, p + pos, ep->sz + 1); strlcat(ep->data, " ", ep->sz + 1); - return(ROFF_IGN); + return ROFF_IGN; } struct eqn_node * @@ -339,7 +339,7 @@ eqn_alloc(int pos, int line, struct mparse *parse) p->eqn.pos = pos; p->gsize = EQN_DEFSIZE; - return(p); + return p; } /* @@ -353,9 +353,9 @@ eqn_def_find(struct eqn_node *ep, const char *key, size_t sz) for (i = 0; i < (int)ep->defsz; i++) if (ep->defs[i].keysz && STRNEQ(ep->defs[i].key, ep->defs[i].keysz, key, sz)) - return(&ep->defs[i]); + return &ep->defs[i]; - return(NULL); + return NULL; } /* @@ -382,7 +382,7 @@ again: if (lim >= EQN_NEST_MAX) { mandoc_msg(MANDOCERR_ROFFLOOP, ep->parse, ep->eqn.ln, ep->eqn.pos, NULL); - return(NULL); + return NULL; } ep->cur = ep->rew; @@ -390,7 +390,7 @@ again: q = 0; if ('\0' == *start) - return(NULL); + return NULL; if (quote == *start) { ep->cur++; @@ -432,7 +432,7 @@ again: /* Quotes aren't expanded for values. */ if (q || ! repl) - return(start); + return start; if (NULL != (def = eqn_def_find(ep, start, *sz))) { diff = def->valsz - *sz; @@ -448,10 +448,11 @@ again: memmove(start + *sz + diff, start + *sz, (strlen(start) - *sz) + 1); memcpy(start, def->val, def->valsz); + lim++; goto again; } - return(start); + return start; } /* @@ -462,7 +463,7 @@ static const char * eqn_nexttok(struct eqn_node *ep, size_t *sz) { - return(eqn_next(ep, '"', sz, 1)); + return eqn_next(ep, '"', sz, 1); } /* @@ -472,7 +473,7 @@ static const char * eqn_nextrawtok(struct eqn_node *ep, size_t *sz) { - return(eqn_next(ep, '"', sz, 0)); + return eqn_next(ep, '"', sz, 0); } /* @@ -498,12 +499,12 @@ eqn_tok_parse(struct eqn_node *ep, char **p) quoted = ep->data[ep->cur] == '"'; if (NULL == (start = eqn_nexttok(ep, &sz))) - return(EQN_TOK_EOF); + return EQN_TOK_EOF; if (quoted) { if (p != NULL) *p = mandoc_strndup(start, sz); - return(EQN_TOK__MAX); + return EQN_TOK__MAX; } for (i = 0; i < EQN_TOK__MAX; i++) { @@ -516,7 +517,7 @@ eqn_tok_parse(struct eqn_node *ep, char **p) if (i == EQN_TOK__MAX && NULL != p) *p = mandoc_strndup(start, sz); - return(i); + return i; } static void @@ -557,7 +558,7 @@ eqn_box_alloc(struct eqn_node *ep, struct eqn_box *parent) parent->first = bp; parent->last = bp; - return(bp); + return bp; } /* @@ -587,7 +588,7 @@ eqn_box_makebinary(struct eqn_node *ep, newb->first = newb->last = b; newb->first->next = NULL; b->parent = newb; - return(newb); + return newb; } /* @@ -712,7 +713,7 @@ eqn_parse(struct eqn_node *ep, struct eqn_box *parent) */ if (ep->data == NULL) - return(ROFF_IGN); + return ROFF_IGN; next_tok: tok = eqn_tok_parse(ep, &p); @@ -986,7 +987,7 @@ this_tok: parent->right = mandoc_strndup(start, sz); } parent = parent->parent; - if (EQN_TOK_BRACE_CLOSE == tok && parent && + if (tok == EQN_TOK_BRACE_CLOSE && (parent->type == EQN_PILE || parent->type == EQN_MATRIX)) parent = parent->parent; @@ -1060,7 +1061,7 @@ this_tok: * End of file! * TODO: make sure we're not in an open subexpression. */ - return(ROFF_EQN); + return ROFF_EQN; default: assert(tok == EQN_TOK__MAX); assert(NULL != p); @@ -1104,7 +1105,7 @@ eqn_end(struct eqn_node **epp) ep->eqn.root = mandoc_calloc(1, sizeof(struct eqn_box)); ep->eqn.root->expectargs = UINT_MAX; - return(eqn_parse(ep, ep->eqn.root)); + return eqn_parse(ep, ep->eqn.root); } void diff --git a/usr/src/cmd/mandoc/html.c b/usr/src/cmd/mandoc/html.c index 487dacda94..adff053c1a 100644 --- a/usr/src/cmd/mandoc/html.c +++ b/usr/src/cmd/mandoc/html.c @@ -1,4 +1,4 @@ -/* $Id: html.c,v 1.185 2015/01/21 20:33:25 schwarze Exp $ */ +/* $Id: html.c,v 1.192 2016/01/04 12:45:29 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -32,6 +32,7 @@ #include "mandoc_aux.h" #include "out.h" #include "html.h" +#include "manconf.h" #include "main.h" struct htmldata { @@ -129,42 +130,20 @@ static void print_attr(struct html *, const char *, const char *); void * -html_alloc(const struct mchars *mchars, char *outopts) +html_alloc(const struct manoutput *outopts) { struct html *h; - const char *toks[5]; - char *v; - - toks[0] = "style"; - toks[1] = "man"; - toks[2] = "includes"; - toks[3] = "fragment"; - toks[4] = NULL; h = mandoc_calloc(1, sizeof(struct html)); h->tags.head = NULL; - h->symtab = mchars; + h->style = outopts->style; + h->base_man = outopts->man; + h->base_includes = outopts->includes; + if (outopts->fragment) + h->oflags |= HTML_FRAGMENT; - while (outopts && *outopts) - switch (getsubopt(&outopts, UNCONST(toks), &v)) { - case 0: - h->style = v; - break; - case 1: - h->base_man = v; - break; - case 2: - h->base_includes = v; - break; - case 3: - h->oflags |= HTML_FRAGMENT; - break; - default: - break; - } - - return(h); + return h; } void @@ -237,13 +216,11 @@ print_metaf(struct html *h, enum mandoc_esc deco) font = HTMLFONT_BI; break; case ESCAPE_FONT: - /* FALLTHROUGH */ case ESCAPE_FONTROMAN: font = HTMLFONT_NONE; break; default: abort(); - /* NOTREACHED */ } if (h->metaf) { @@ -301,13 +278,10 @@ html_strlen(const char *cp) cp++; switch (mandoc_escape(&cp, NULL, NULL)) { case ESCAPE_ERROR: - return(sz); + return sz; case ESCAPE_UNICODE: - /* FALLTHROUGH */ case ESCAPE_NUMBERED: - /* FALLTHROUGH */ case ESCAPE_SPECIAL: - /* FALLTHROUGH */ case ESCAPE_OVERSTRIKE: if (skip) skip = 0; @@ -321,7 +295,7 @@ html_strlen(const char *cp) break; } } - return(sz); + return sz; } static int @@ -342,17 +316,17 @@ print_escape(char c) printf("""); break; case ASCII_NBRSP: - putchar('-'); + printf(" "); break; case ASCII_HYPH: putchar('-'); - /* FALLTHROUGH */ + break; case ASCII_BREAK: break; default: - return(0); + return 0; } - return(1); + return 1; } static int @@ -391,15 +365,10 @@ print_encode(struct html *h, const char *p, int norecurse) switch (esc) { case ESCAPE_FONT: - /* FALLTHROUGH */ case ESCAPE_FONTPREV: - /* FALLTHROUGH */ case ESCAPE_FONTBOLD: - /* FALLTHROUGH */ case ESCAPE_FONTITALIC: - /* FALLTHROUGH */ case ESCAPE_FONTBI: - /* FALLTHROUGH */ case ESCAPE_FONTROMAN: if (0 == norecurse) print_metaf(h, esc); @@ -427,7 +396,7 @@ print_encode(struct html *h, const char *p, int norecurse) continue; break; case ESCAPE_SPECIAL: - c = mchars_spec2cp(h->symtab, seq, len); + c = mchars_spec2cp(seq, len); if (c <= 0) continue; break; @@ -452,7 +421,7 @@ print_encode(struct html *h, const char *p, int norecurse) putchar(c); } - return(nospace); + return nospace; } static void @@ -514,7 +483,7 @@ print_otag(struct html *h, enum htmltag tag, if ((HTML_AUTOCLOSE | HTML_CLRLINE) & htmltags[tag].flags) putchar('\n'); - return(t); + return t; } static void @@ -751,8 +720,8 @@ void bufcat_id(struct html *h, const char *src) { - /* Cf. <http://www.w3.org/TR/html4/types.html#h-6.2>. */ + /* Cf. <http://www.w3.org/TR/html5/dom.html#the-id-attribute>. */ - while ('\0' != *src) - bufcat_fmt(h, "%.2x", *src++); + for (; '\0' != *src; src++) + bufncat(h, *src == ' ' ? "_" : src, 1); } diff --git a/usr/src/cmd/mandoc/html.h b/usr/src/cmd/mandoc/html.h index bbf6183cc5..27dc140185 100644 --- a/usr/src/cmd/mandoc/html.h +++ b/usr/src/cmd/mandoc/html.h @@ -1,4 +1,4 @@ -/* $Id: html.h,v 1.70 2014/12/02 10:08:06 schwarze Exp $ */ +/* $Id: html.h,v 1.72 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -130,7 +130,6 @@ struct html { struct tagq tags; /* stack of open tags */ struct rofftbl tbl; /* current table */ struct tag *tblt; /* current open table scope */ - const struct mchars *symtab; /* character table */ char *base_man; /* base for manpage href */ char *base_includes; /* base for include href */ char *style; /* style-sheet URI */ @@ -143,7 +142,6 @@ struct html { #define HTML_FRAGMENT (1 << 0) /* don't emit HTML/HEAD/BODY */ }; -__BEGIN_DECLS struct tbl_span; struct eqn; @@ -176,5 +174,3 @@ void buffmt_man(struct html *, void buffmt_includes(struct html *, const char *); int html_strlen(const char *); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/lib.c b/usr/src/cmd/mandoc/lib.c index 17ce5296de..5295950b09 100644 --- a/usr/src/cmd/mandoc/lib.c +++ b/usr/src/cmd/mandoc/lib.c @@ -1,4 +1,4 @@ -/* $Id: lib.c,v 1.11 2014/08/10 23:54:41 schwarze Exp $ */ +/* $Id: lib.c,v 1.13 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -20,6 +20,7 @@ #include <string.h> +#include "roff.h" #include "mdoc.h" #include "libmdoc.h" @@ -32,5 +33,5 @@ mdoc_a2lib(const char *p) #include "lib.in" - return(NULL); + return NULL; } diff --git a/usr/src/cmd/mandoc/libman.h b/usr/src/cmd/mandoc/libman.h index 8d115b3abe..65849602c2 100644 --- a/usr/src/cmd/mandoc/libman.h +++ b/usr/src/cmd/mandoc/libman.h @@ -1,44 +1,23 @@ -/* $Id: libman.h,v 1.67 2014/12/28 14:42:27 schwarze Exp $ */ +/* $Id: libman.h,v 1.79 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -enum man_next { - MAN_NEXT_SIBLING = 0, - MAN_NEXT_CHILD -}; - -struct man { - struct mparse *parse; /* parse pointer */ - const char *defos; /* default OS argument for .TH */ - int quick; /* abort parse early */ - int flags; /* parse flags */ -#define MAN_ELINE (1 << 1) /* Next-line element scope. */ -#define MAN_BLINE (1 << 2) /* Next-line block scope. */ -#define MAN_LITERAL (1 << 4) /* Literal input. */ -#define MAN_NEWLINE (1 << 6) /* first macro/text in a line */ - enum man_next next; /* where to put the next node */ - struct man_node *last; /* the last parsed node */ - struct man_node *first; /* the first parsed node */ - struct man_meta meta; /* document meta-data */ - struct roff *roff; -}; - -#define MACRO_PROT_ARGS struct man *man, \ - enum mant tok, \ +#define MACRO_PROT_ARGS struct roff_man *man, \ + int tok, \ int line, \ int ppos, \ int *pos, \ @@ -47,30 +26,16 @@ struct man { struct man_macro { void (*fp)(MACRO_PROT_ARGS); int flags; -#define MAN_SCOPED (1 << 0) -#define MAN_EXPLICIT (1 << 1) /* See blk_imp(). */ -#define MAN_FSCOPED (1 << 2) /* See blk_imp(). */ -#define MAN_NSCOPED (1 << 3) /* See in_line_eoln(). */ -#define MAN_NOCLOSE (1 << 4) /* See blk_exp(). */ -#define MAN_BSCOPE (1 << 5) /* Break BLINE scope. */ -#define MAN_JOIN (1 << 6) /* Join arguments together. */ +#define MAN_SCOPED (1 << 0) /* Optional next-line scope. */ +#define MAN_NSCOPED (1 << 1) /* Allowed in next-line element scope. */ +#define MAN_BSCOPE (1 << 2) /* Break next-line block scope. */ +#define MAN_JOIN (1 << 3) /* Join arguments together. */ }; extern const struct man_macro *const man_macros; -__BEGIN_DECLS - -void man_word_alloc(struct man *, int, int, const char *); -void man_word_append(struct man *, const char *); -void man_block_alloc(struct man *, int, int, enum mant); -void man_head_alloc(struct man *, int, int, enum mant); -void man_body_alloc(struct man *, int, int, enum mant); -void man_elem_alloc(struct man *, int, int, enum mant); -void man_node_delete(struct man *, struct man_node *); -void man_hash_init(void); -enum mant man_hash_find(const char *); -void man_macroend(struct man *); -void man_valid_post(struct man *); -void man_unscope(struct man *, const struct man_node *); -__END_DECLS +int man_hash_find(const char *); +void man_node_validate(struct roff_man *); +void man_state(struct roff_man *, struct roff_node *); +void man_unscope(struct roff_man *, const struct roff_node *); diff --git a/usr/src/cmd/mandoc/libmandoc.h b/usr/src/cmd/mandoc/libmandoc.h index 11feebdc10..9ed8f15049 100644 --- a/usr/src/cmd/mandoc/libmandoc.h +++ b/usr/src/cmd/mandoc/libmandoc.h @@ -1,15 +1,15 @@ -/* $Id: libmandoc.h,v 1.55 2015/01/15 04:26:39 schwarze Exp $ */ +/* $Id: libmandoc.h,v 1.63 2016/07/07 19:19:01 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -32,15 +32,12 @@ struct buf { size_t sz; }; -__BEGIN_DECLS struct mparse; -struct mchars; struct tbl_span; struct eqn; struct roff; -struct mdoc; -struct man; +struct roff_man; void mandoc_msg(enum mandocerr, struct mparse *, int, int, const char *); @@ -55,31 +52,25 @@ int mandoc_eos(const char *, size_t); int mandoc_strntoi(const char *, size_t, int); const char *mandoc_a2msec(const char*); -void mdoc_free(struct mdoc *); -struct mdoc *mdoc_alloc(struct roff *, struct mparse *, - const char *, int); -void mdoc_reset(struct mdoc *); -int mdoc_parseln(struct mdoc *, int, char *, int); -void mdoc_endparse(struct mdoc *); -void mdoc_addspan(struct mdoc *, const struct tbl_span *); -void mdoc_addeqn(struct mdoc *, const struct eqn *); +void mdoc_hash_init(void); +int mdoc_parseln(struct roff_man *, int, char *, int); +void mdoc_endparse(struct roff_man *); -void man_free(struct man *); -struct man *man_alloc(struct roff *, struct mparse *, - const char *, int); -void man_reset(struct man *); -int man_parseln(struct man *, int, char *, int); -void man_endparse(struct man *); -void man_addspan(struct man *, const struct tbl_span *); -void man_addeqn(struct man *, const struct eqn *); +void man_hash_init(void); +int man_parseln(struct roff_man *, int, char *, int); +void man_endparse(struct roff_man *); int preconv_cue(const struct buf *, size_t); int preconv_encode(struct buf *, size_t *, struct buf *, size_t *, int *); void roff_free(struct roff *); -struct roff *roff_alloc(struct mparse *, const struct mchars *, int); +struct roff *roff_alloc(struct mparse *, int); void roff_reset(struct roff *); +void roff_man_free(struct roff_man *); +struct roff_man *roff_man_alloc(struct roff *, struct mparse *, + const char *, int); +void roff_man_reset(struct roff_man *); enum rofferr roff_parseln(struct roff *, int, struct buf *, int *); void roff_endparse(struct roff *); void roff_setreg(struct roff *, const char *, int, char sign); @@ -91,5 +82,3 @@ int roff_getformat(const struct roff *); const struct tbl_span *roff_span(const struct roff *); const struct eqn *roff_eqn(const struct roff *); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/libmdoc.h b/usr/src/cmd/mandoc/libmdoc.h index 527fe02703..5a6cc3ed9b 100644 --- a/usr/src/cmd/mandoc/libmdoc.h +++ b/usr/src/cmd/mandoc/libmdoc.h @@ -1,53 +1,23 @@ -/* $Id: libmdoc.h,v 1.97 2015/02/02 04:26:44 schwarze Exp $ */ +/* $Id: libmdoc.h,v 1.108 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -enum mdoc_next { - MDOC_NEXT_SIBLING = 0, - MDOC_NEXT_CHILD -}; - -struct mdoc { - struct mparse *parse; /* parse pointer */ - const char *defos; /* default argument for .Os */ - int quick; /* abort parse early */ - int flags; /* parse flags */ -#define MDOC_LITERAL (1 << 1) /* in a literal scope */ -#define MDOC_PBODY (1 << 2) /* in the document body */ -#define MDOC_NEWLINE (1 << 3) /* first macro/text in a line */ -#define MDOC_PHRASELIT (1 << 4) /* literal within a partila phrase */ -#define MDOC_PPHRASE (1 << 5) /* within a partial phrase */ -#define MDOC_FREECOL (1 << 6) /* `It' invocation should close */ -#define MDOC_SYNOPSIS (1 << 7) /* SYNOPSIS-style formatting */ -#define MDOC_KEEP (1 << 8) /* in a word keep */ -#define MDOC_SMOFF (1 << 9) /* spacing is off */ -#define MDOC_NODELIMC (1 << 10) /* disable closing delimiter handling */ - enum mdoc_next next; /* where to put the next node */ - struct mdoc_node *last; /* the last node parsed */ - struct mdoc_node *first; /* the first node parsed */ - struct mdoc_node *last_es; /* the most recent Es node */ - struct mdoc_meta meta; /* document meta-data */ - enum mdoc_sec lastnamed; - enum mdoc_sec lastsec; - struct roff *roff; -}; - -#define MACRO_PROT_ARGS struct mdoc *mdoc, \ - enum mdoct tok, \ +#define MACRO_PROT_ARGS struct roff_man *mdoc, \ + int tok, \ int line, \ int ppos, \ int *pos, \ @@ -70,9 +40,7 @@ enum margserr { ARGS_WORD, /* normal word */ ARGS_PUNCT, /* series of punctuation */ ARGS_QWORD, /* quoted word */ - ARGS_PHRASE, /* Ta'd phrase (-column) */ - ARGS_PPHRASE, /* tabbed phrase (-column) */ - ARGS_PEND /* last phrase (-column) */ + ARGS_PHRASE /* Bl -column phrase */ }; /* @@ -94,36 +62,27 @@ enum mdelim { extern const struct mdoc_macro *const mdoc_macros; -__BEGIN_DECLS void mdoc_macro(MACRO_PROT_ARGS); -void mdoc_word_alloc(struct mdoc *, int, int, const char *); -void mdoc_word_append(struct mdoc *, const char *); -void mdoc_elem_alloc(struct mdoc *, int, int, - enum mdoct, struct mdoc_arg *); -struct mdoc_node *mdoc_block_alloc(struct mdoc *, int, int, - enum mdoct, struct mdoc_arg *); -struct mdoc_node *mdoc_head_alloc(struct mdoc *, int, int, enum mdoct); -void mdoc_tail_alloc(struct mdoc *, int, int, enum mdoct); -struct mdoc_node *mdoc_body_alloc(struct mdoc *, int, int, enum mdoct); -struct mdoc_node *mdoc_endbody_alloc(struct mdoc *, int, int, enum mdoct, - struct mdoc_node *, enum mdoc_endbody); -void mdoc_node_delete(struct mdoc *, struct mdoc_node *); -void mdoc_node_relink(struct mdoc *, struct mdoc_node *); -void mdoc_hash_init(void); -enum mdoct mdoc_hash_find(const char *); +void mdoc_elem_alloc(struct roff_man *, int, int, + int, struct mdoc_arg *); +struct roff_node *mdoc_block_alloc(struct roff_man *, int, int, + int, struct mdoc_arg *); +void mdoc_tail_alloc(struct roff_man *, int, int, int); +struct roff_node *mdoc_endbody_alloc(struct roff_man *, int, int, int, + struct roff_node *, enum mdoc_endbody); +void mdoc_node_relink(struct roff_man *, struct roff_node *); +void mdoc_node_validate(struct roff_man *); +void mdoc_state(struct roff_man *, struct roff_node *); +void mdoc_state_reset(struct roff_man *); +int mdoc_hash_find(const char *); +const char *mdoc_a2arch(const char *); const char *mdoc_a2att(const char *); const char *mdoc_a2lib(const char *); +enum roff_sec mdoc_a2sec(const char *); const char *mdoc_a2st(const char *); -const char *mdoc_a2arch(const char *); -void mdoc_valid_pre(struct mdoc *, struct mdoc_node *); -void mdoc_valid_post(struct mdoc *); -void mdoc_argv(struct mdoc *, int, enum mdoct, +void mdoc_argv(struct roff_man *, int, int, struct mdoc_arg **, int *, char *); -void mdoc_argv_free(struct mdoc_arg *); -enum margserr mdoc_args(struct mdoc *, int, - int *, char *, enum mdoct, char **); -void mdoc_macroend(struct mdoc *); +enum margserr mdoc_args(struct roff_man *, int, + int *, char *, int, char **); enum mdelim mdoc_isdelim(const char *); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/libroff.h b/usr/src/cmd/mandoc/libroff.h index 08ed1f7925..897a55ae61 100644 --- a/usr/src/cmd/mandoc/libroff.h +++ b/usr/src/cmd/mandoc/libroff.h @@ -1,4 +1,4 @@ -/* $Id: libroff.h,v 1.38 2015/01/30 04:11:50 schwarze Exp $ */ +/* $Id: libroff.h,v 1.39 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -60,7 +60,6 @@ struct eqn_def { size_t valsz; }; -__BEGIN_DECLS struct tbl_node *tbl_alloc(int, int, struct mparse *); void tbl_restart(int, int, struct tbl_node *); @@ -78,5 +77,3 @@ enum rofferr eqn_end(struct eqn_node **); void eqn_free(struct eqn_node *); enum rofferr eqn_read(struct eqn_node **, int, const char *, int, int *); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/main.c b/usr/src/cmd/mandoc/main.c index f0cd8ca0cc..0dd6bb5dcc 100644 --- a/usr/src/cmd/mandoc/main.c +++ b/usr/src/cmd/mandoc/main.c @@ -1,16 +1,16 @@ -/* $Id: main.c,v 1.225 2015/03/10 13:50:03 schwarze Exp $ */ +/* $Id: main.c,v 1.269 2016/07/12 05:18:38 kristaps Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010-2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010-2012, 2014-2016 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -24,21 +24,31 @@ #include <assert.h> #include <ctype.h> +#if HAVE_ERR +#include <err.h> +#endif #include <errno.h> #include <fcntl.h> #include <glob.h> +#if HAVE_SANDBOX_INIT +#include <sandbox.h> +#endif +#include <signal.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <time.h> #include <unistd.h> -#include "mandoc.h" #include "mandoc_aux.h" -#include "main.h" +#include "mandoc.h" +#include "roff.h" #include "mdoc.h" #include "man.h" -#include "manpath.h" +#include "tag.h" +#include "main.h" +#include "manconf.h" #include "mansearch.h" #if !defined(__GNUC__) || (__GNUC__ < 2) @@ -56,10 +66,6 @@ enum outmode { OUTMODE_ONE }; -typedef void (*out_mdoc)(void *, const struct mdoc *); -typedef void (*out_man)(void *, const struct man *); -typedef void (*out_free)(void *); - enum outt { OUTT_ASCII = 0, /* -Tascii */ OUTT_LOCALE, /* -Tlocale */ @@ -74,15 +80,11 @@ enum outt { struct curparse { struct mparse *mp; - struct mchars *mchars; /* character table */ enum mandoclevel wlevel; /* ignore messages below this */ int wstop; /* stop after a file with a warning */ enum outt outtype; /* which output to use */ - out_mdoc outmdoc; /* mdoc output ptr */ - out_man outman; /* man output ptr */ - out_free outfree; /* free output ptr */ void *outdata; /* data for output */ - char outopts[BUFSIZ]; /* buf of output opts */ + struct manoutput *outopts; /* output options */ }; static int fs_lookup(const struct manpaths *, @@ -99,10 +101,9 @@ int mandocdb(int, char**); static int moptions(int *, char *); static void mmsg(enum mandocerr, enum mandoclevel, const char *, int, int, const char *); -static void parse(struct curparse *, int, - const char *, enum mandoclevel *); -static enum mandoclevel passthrough(const char *, int, int); -static pid_t spawn_pager(void); +static void parse(struct curparse *, int, const char *); +static void passthrough(const char *, int, int); +static pid_t spawn_pager(struct tag_files *); static int toptions(struct curparse *, char *); static void usage(enum argmode) __attribute__((noreturn)); static int woptions(struct curparse *, char *); @@ -110,46 +111,65 @@ static int woptions(struct curparse *, char *); static const int sec_prios[] = {1, 4, 5, 8, 6, 3, 7, 2, 9}; static char help_arg[] = "help"; static char *help_argv[] = {help_arg, NULL}; -static const char *progname; +static enum mandoclevel rc; int main(int argc, char *argv[]) { + struct manconf conf; struct curparse curp; struct mansearch search; - struct manpaths paths; + struct tag_files *tag_files; + const char *progname; char *auxpaths; char *defos; unsigned char *uc; struct manpage *res, *resp; char *conf_file, *defpaths; - size_t isec, i, sz; - int prio, best_prio, synopsis_only; - char sec; - enum mandoclevel rc, rctmp; + const char *sec; + size_t i, sz; + int prio, best_prio; enum outmode outmode; int fd; int show_usage; int options; + int use_pager; + int status, signum; int c; - pid_t pager_pid; /* 0: don't use; 1: not yet spawned. */ + pid_t pager_pid, tc_pgid, man_pgid, pid; +#if HAVE_PROGNAME + progname = getprogname(); +#else if (argc < 1) - progname = "mandoc"; + progname = mandoc_strdup("mandoc"); else if ((progname = strrchr(argv[0], '/')) == NULL) progname = argv[0]; else ++progname; + setprogname(progname); +#endif #if HAVE_SQLITE3 - if (strcmp(progname, BINM_MAKEWHATIS) == 0) - return(mandocdb(argc, argv)); + if (strncmp(progname, "mandocdb", 8) == 0 || + strcmp(progname, BINM_MAKEWHATIS) == 0) + return mandocdb(argc, argv); +#endif + +#if HAVE_PLEDGE + if (pledge("stdio rpath tmppath tty proc exec flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + +#if HAVE_SANDBOX_INIT + if (sandbox_init(kSBXProfileNoInternet, SANDBOX_NAMED, NULL) == -1) + errx((int)MANDOCLEVEL_SYSERR, "sandbox_init"); #endif /* Search options. */ - memset(&paths, 0, sizeof(struct manpaths)); + memset(&conf, 0, sizeof(conf)); conf_file = defpaths = NULL; auxpaths = NULL; @@ -172,12 +192,13 @@ main(int argc, char *argv[]) memset(&curp, 0, sizeof(struct curparse)); curp.outtype = OUTT_LOCALE; curp.wlevel = MANDOCLEVEL_BADARG; + curp.outopts = &conf.output; options = MPARSE_SO | MPARSE_UTF8 | MPARSE_LATIN1; defos = NULL; - pager_pid = 1; + use_pager = 1; + tag_files = NULL; show_usage = 0; - synopsis_only = 0; outmode = OUTMODE_DEF; while (-1 != (c = getopt(argc, argv, @@ -190,29 +211,24 @@ main(int argc, char *argv[]) conf_file = optarg; break; case 'c': - pager_pid = 0; + use_pager = 0; break; case 'f': search.argmode = ARG_WORD; break; case 'h': - (void)strlcat(curp.outopts, "synopsis,", BUFSIZ); - synopsis_only = 1; - pager_pid = 0; + conf.output.synopsisonly = 1; + use_pager = 0; outmode = OUTMODE_ALL; break; case 'I': if (strncmp(optarg, "os=", 3)) { - fprintf(stderr, - "%s: -I %s: Bad argument\n", - progname, optarg); - return((int)MANDOCLEVEL_BADARG); + warnx("-I %s: Bad argument", optarg); + return (int)MANDOCLEVEL_BADARG; } if (defos) { - fprintf(stderr, - "%s: -I %s: Duplicate argument\n", - progname, optarg); - return((int)MANDOCLEVEL_BADARG); + warnx("-I %s: Duplicate argument", optarg); + return (int)MANDOCLEVEL_BADARG; } defos = mandoc_strdup(optarg + 3); break; @@ -221,7 +237,7 @@ main(int argc, char *argv[]) break; case 'K': if ( ! koptions(&options, optarg)) - return((int)MANDOCLEVEL_BADARG); + return (int)MANDOCLEVEL_BADARG; break; case 'k': search.argmode = ARG_EXPR; @@ -238,8 +254,9 @@ main(int argc, char *argv[]) break; case 'O': search.outkey = optarg; - (void)strlcat(curp.outopts, optarg, BUFSIZ); - (void)strlcat(curp.outopts, ",", BUFSIZ); + while (optarg != NULL) + manconf_output(&conf.output, + strsep(&optarg, ",")); break; case 'S': search.arch = optarg; @@ -249,11 +266,11 @@ main(int argc, char *argv[]) break; case 'T': if ( ! toptions(&curp, optarg)) - return((int)MANDOCLEVEL_BADARG); + return (int)MANDOCLEVEL_BADARG; break; case 'W': if ( ! woptions(&curp, optarg)) - return((int)MANDOCLEVEL_BADARG); + return (int)MANDOCLEVEL_BADARG; break; case 'w': outmode = OUTMODE_FLN; @@ -273,7 +290,7 @@ main(int argc, char *argv[]) switch (search.argmode) { case ARG_FILE: outmode = OUTMODE_ALL; - pager_pid = 0; + use_pager = 0; break; case ARG_NAME: outmode = OUTMODE_ONE; @@ -284,6 +301,17 @@ main(int argc, char *argv[]) } } + if (outmode == OUTMODE_FLN || + outmode == OUTMODE_LST || + !isatty(STDOUT_FILENO)) + use_pager = 0; + +#if HAVE_PLEDGE + if (!use_pager) + if (pledge("stdio rpath flock", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + /* Parse arguments. */ if (argc > 0) { @@ -334,22 +362,28 @@ main(int argc, char *argv[]) /* Access the mandoc database. */ - manpath_parse(&paths, conf_file, defpaths, auxpaths); + manconf_parse(&conf, conf_file, defpaths, auxpaths); #if HAVE_SQLITE3 mansearch_setup(1); - if( ! mansearch(&search, &paths, argc, argv, &res, &sz)) + if ( ! mansearch(&search, &conf.manpath, + argc, argv, &res, &sz)) usage(search.argmode); #else if (search.argmode != ARG_NAME) { fputs("mandoc: database support not compiled in\n", stderr); - return((int)MANDOCLEVEL_BADARG); + return (int)MANDOCLEVEL_BADARG; } sz = 0; #endif - if (sz == 0 && search.argmode == ARG_NAME) - fs_search(&search, &paths, argc, argv, &res, &sz); + if (sz == 0) { + if (search.argmode == ARG_NAME) + fs_search(&search, &conf.manpath, + argc, argv, &res, &sz); + else + warnx("nothing appropriate"); + } if (sz == 0) { rc = MANDOCLEVEL_BADARG; @@ -364,7 +398,7 @@ main(int argc, char *argv[]) if (outmode == OUTMODE_ONE) { argc = 1; - best_prio = 10; + best_prio = 20; } else if (outmode == OUTMODE_ALL) argc = (int)sz; @@ -380,11 +414,13 @@ main(int argc, char *argv[]) res[i].output); else if (outmode == OUTMODE_ONE) { /* Search for the best section. */ - isec = strcspn(res[i].file, "123456789"); - sec = res[i].file[isec]; - if ('\0' == sec) + sec = res[i].file; + sec += strcspn(sec, "123456789"); + if (sec[0] == '\0') continue; - prio = sec_prios[sec - '1']; + prio = sec_prios[sec[0] - '1']; + if (sec[1] != '/') + prio += 10; if (prio >= best_prio) continue; best_prio = prio; @@ -404,12 +440,21 @@ main(int argc, char *argv[]) /* mandoc(1) */ +#if HAVE_PLEDGE + if (use_pager) { + if (pledge("stdio rpath tmppath tty proc exec", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); + } else { + if (pledge("stdio rpath", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); + } +#endif + if (search.argmode == ARG_FILE && ! moptions(&options, auxpaths)) - return((int)MANDOCLEVEL_BADARG); + return (int)MANDOCLEVEL_BADARG; - curp.mchars = mchars_alloc(); - curp.mp = mparse_alloc(options, curp.wlevel, mmsg, - curp.mchars, defos); + mchars_alloc(); + curp.mp = mparse_alloc(options, curp.wlevel, mmsg, defos); /* * Conditionally start up the lookaside buffer before parsing. @@ -418,41 +463,33 @@ main(int argc, char *argv[]) mparse_keep(curp.mp); if (argc < 1) { - if (pager_pid == 1 && isatty(STDOUT_FILENO)) - pager_pid = spawn_pager(); - parse(&curp, STDIN_FILENO, "<stdin>", &rc); + if (use_pager) + tag_files = tag_init(); + parse(&curp, STDIN_FILENO, "<stdin>"); } while (argc > 0) { - rctmp = mparse_open(curp.mp, &fd, - resp != NULL ? resp->file : *argv); - if (rc < rctmp) - rc = rctmp; - + fd = mparse_open(curp.mp, resp != NULL ? resp->file : *argv); if (fd != -1) { - if (pager_pid == 1 && isatty(STDOUT_FILENO)) - pager_pid = spawn_pager(); + if (use_pager) { + tag_files = tag_init(); + use_pager = 0; + } if (resp == NULL) - parse(&curp, fd, *argv, &rc); + parse(&curp, fd, *argv); else if (resp->form & FORM_SRC) { /* For .so only; ignore failure. */ - chdir(paths.paths[resp->ipath]); - parse(&curp, fd, resp->file, &rc); - } else { - rctmp = passthrough(resp->file, fd, - synopsis_only); - if (rc < rctmp) - rc = rctmp; - } - - rctmp = mparse_wait(curp.mp); - if (rc < rctmp) - rc = rctmp; + chdir(conf.manpath.paths[resp->ipath]); + parse(&curp, fd, resp->file); + } else + passthrough(resp->file, fd, + conf.output.synopsisonly); if (argc > 1 && curp.outtype <= OUTT_UTF8) - ascii_sepline(curp.outdata); - } + terminal_sepline(curp.outdata); + } else if (rc < MANDOCLEVEL_ERROR) + rc = MANDOCLEVEL_ERROR; if (MANDOCLEVEL_OK != rc && curp.wstop) break; @@ -465,14 +502,30 @@ main(int argc, char *argv[]) mparse_reset(curp.mp); } - if (curp.outfree) - (*curp.outfree)(curp.outdata); + if (curp.outdata != NULL) { + switch (curp.outtype) { + case OUTT_HTML: + html_free(curp.outdata); + break; + case OUTT_UTF8: + case OUTT_LOCALE: + case OUTT_ASCII: + ascii_free(curp.outdata); + break; + case OUTT_PDF: + case OUTT_PS: + pspdf_free(curp.outdata); + break; + default: + break; + } + } mparse_free(curp.mp); - mchars_free(curp.mchars); + mchars_free(); out: if (search.argmode != ARG_FILE) { - manpath_free(&paths); + manconf_free(&conf); #if HAVE_SQLITE3 mansearch_free(res, sz); mansearch_setup(0); @@ -482,17 +535,63 @@ out: free(defos); /* - * If a pager is attached, flush the pipe leading to it - * and signal end of file such that the user can browse - * to the end. Then wait for the user to close the pager. + * When using a pager, finish writing both temporary files, + * fork it, wait for the user to close it, and clean up. */ - if (pager_pid != 0 && pager_pid != 1) { + if (tag_files != NULL) { fclose(stdout); - waitpid(pager_pid, NULL, 0); + tag_write(); + man_pgid = getpgid(0); + tag_files->tcpgid = man_pgid == getpid() ? + getpgid(getppid()) : man_pgid; + pager_pid = 0; + signum = SIGSTOP; + for (;;) { + + /* Stop here until moved to the foreground. */ + + tc_pgid = tcgetpgrp(STDIN_FILENO); + if (tc_pgid != man_pgid) { + if (tc_pgid == pager_pid) { + (void)tcsetpgrp(STDIN_FILENO, + man_pgid); + if (signum == SIGTTIN) + continue; + } else + tag_files->tcpgid = tc_pgid; + kill(0, signum); + continue; + } + + /* Once in the foreground, activate the pager. */ + + if (pager_pid) { + (void)tcsetpgrp(STDIN_FILENO, pager_pid); + kill(pager_pid, SIGCONT); + } else + pager_pid = spawn_pager(tag_files); + + /* Wait for the pager to stop or exit. */ + + while ((pid = waitpid(pager_pid, &status, + WUNTRACED)) == -1 && errno == EINTR) + continue; + + if (pid == -1) { + warn("wait"); + rc = MANDOCLEVEL_SYSERR; + break; + } + if (!WIFSTOPPED(status)) + break; + + signum = WSTOPSIG(status); + } + tag_unlink(); } - return((int)rc); + return (int)rc; } static void @@ -501,9 +600,9 @@ usage(enum argmode argmode) switch (argmode) { case ARG_FILE: - fputs("usage: mandoc [-acfhkl] [-Ios=name] " - "[-Kencoding] [-mformat] [-Ooption]\n" - "\t [-Toutput] [-Wlevel] [file ...]\n", stderr); + fputs("usage: mandoc [-acfhkl] [-I os=name] " + "[-K encoding] [-mformat] [-O option]\n" + "\t [-T output] [-W level] [file ...]\n", stderr); break; case ARG_NAME: fputs("usage: man [-acfhklw] [-C file] [-I os=name] " @@ -559,26 +658,23 @@ fs_lookup(const struct manpaths *paths, size_t ipath, free(file); } - mandoc_asprintf(&file, "%s/man%s/%s.*", + mandoc_asprintf(&file, "%s/man%s/%s.[01-9]*", paths->paths[ipath], sec, name); globres = glob(file, 0, NULL, &globinfo); if (globres != 0 && globres != GLOB_NOMATCH) - fprintf(stderr, "%s: %s: glob: %s\n", - progname, file, strerror(errno)); + warn("%s: glob", file); free(file); if (globres == 0) file = mandoc_strdup(*globinfo.gl_pathv); globfree(&globinfo); if (globres != 0) - return(0); + return 0; found: #if HAVE_SQLITE3 - fprintf(stderr, "%s: outdated mandoc.db lacks %s(%s) entry,\n" - " consider running # makewhatis %s\n", - progname, name, sec, paths->paths[ipath]); + warnx("outdated mandoc.db lacks %s(%s) entry, run %s %s", + name, sec, BINM_MAKEWHATIS, paths->paths[ipath]); #endif - *res = mandoc_reallocarray(*res, ++*ressz, sizeof(struct manpage)); page = *res + (*ressz - 1); page->file = file; @@ -588,7 +684,7 @@ found: page->bits = NAME_FILE & NAME_MASK; page->sec = (*sec >= '1' && *sec <= '9') ? *sec - '1' + 1 : 10; page->form = form; - return(1); + return 1; } static void @@ -596,7 +692,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths, int argc, char **argv, struct manpage **res, size_t *ressz) { const char *const sections[] = - {"1", "8", "6", "2", "3", "3p", "5", "7", "4", "9"}; + {"1", "8", "6", "2", "3", "5", "7", "4", "9", "3p"}; const size_t nsec = sizeof(sections)/sizeof(sections[0]); size_t ipath, isec, lastsz; @@ -619,9 +715,7 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths, return; } if (*ressz == lastsz) - fprintf(stderr, - "%s: No entry for %s in the manual.\n", - progname, *argv); + warnx("No entry for %s in the manual.", *argv); lastsz = *ressz; argv++; argc--; @@ -629,111 +723,112 @@ fs_search(const struct mansearch *cfg, const struct manpaths *paths, } static void -parse(struct curparse *curp, int fd, const char *file, - enum mandoclevel *level) +parse(struct curparse *curp, int fd, const char *file) { - enum mandoclevel rc; - struct mdoc *mdoc; - struct man *man; + enum mandoclevel rctmp; + struct roff_man *man; /* Begin by parsing the file itself. */ assert(file); - assert(fd >= -1); + assert(fd >= 0); - rc = mparse_readfd(curp->mp, fd, file); + rctmp = mparse_readfd(curp->mp, fd, file); + if (fd != STDIN_FILENO) + close(fd); + if (rc < rctmp) + rc = rctmp; /* * With -Wstop and warnings or errors of at least the requested * level, do not produce output. */ - if (MANDOCLEVEL_OK != rc && curp->wstop) - goto cleanup; + if (rctmp != MANDOCLEVEL_OK && curp->wstop) + return; /* If unset, allocate output dev now (if applicable). */ - if ( ! (curp->outman && curp->outmdoc)) { + if (curp->outdata == NULL) { switch (curp->outtype) { case OUTT_HTML: - curp->outdata = html_alloc(curp->mchars, - curp->outopts); - curp->outfree = html_free; + curp->outdata = html_alloc(curp->outopts); break; case OUTT_UTF8: - curp->outdata = utf8_alloc(curp->mchars, - curp->outopts); - curp->outfree = ascii_free; + curp->outdata = utf8_alloc(curp->outopts); break; case OUTT_LOCALE: - curp->outdata = locale_alloc(curp->mchars, - curp->outopts); - curp->outfree = ascii_free; + curp->outdata = locale_alloc(curp->outopts); break; case OUTT_ASCII: - curp->outdata = ascii_alloc(curp->mchars, - curp->outopts); - curp->outfree = ascii_free; + curp->outdata = ascii_alloc(curp->outopts); break; case OUTT_PDF: - curp->outdata = pdf_alloc(curp->mchars, - curp->outopts); - curp->outfree = pspdf_free; + curp->outdata = pdf_alloc(curp->outopts); break; case OUTT_PS: - curp->outdata = ps_alloc(curp->mchars, - curp->outopts); - curp->outfree = pspdf_free; + curp->outdata = ps_alloc(curp->outopts); break; default: break; } + } + + mparse_result(curp->mp, &man, NULL); + /* Execute the out device, if it exists. */ + + if (man == NULL) + return; + if (man->macroset == MACROSET_MDOC) { + mdoc_validate(man); switch (curp->outtype) { case OUTT_HTML: - curp->outman = html_man; - curp->outmdoc = html_mdoc; + html_mdoc(curp->outdata, man); break; case OUTT_TREE: - curp->outman = tree_man; - curp->outmdoc = tree_mdoc; + tree_mdoc(curp->outdata, man); break; case OUTT_MAN: - curp->outmdoc = man_mdoc; - curp->outman = man_man; + man_mdoc(curp->outdata, man); break; case OUTT_PDF: - /* FALLTHROUGH */ case OUTT_ASCII: - /* FALLTHROUGH */ case OUTT_UTF8: - /* FALLTHROUGH */ case OUTT_LOCALE: - /* FALLTHROUGH */ case OUTT_PS: - curp->outman = terminal_man; - curp->outmdoc = terminal_mdoc; + terminal_mdoc(curp->outdata, man); + break; + default: + break; + } + } + if (man->macroset == MACROSET_MAN) { + man_validate(man); + switch (curp->outtype) { + case OUTT_HTML: + html_man(curp->outdata, man); + break; + case OUTT_TREE: + tree_man(curp->outdata, man); + break; + case OUTT_MAN: + man_man(curp->outdata, man); + break; + case OUTT_PDF: + case OUTT_ASCII: + case OUTT_UTF8: + case OUTT_LOCALE: + case OUTT_PS: + terminal_man(curp->outdata, man); break; default: break; } } - - mparse_result(curp->mp, &mdoc, &man, NULL); - - /* Execute the out device, if it exists. */ - - if (man && curp->outman) - (*curp->outman)(curp->outdata, man); - if (mdoc && curp->outmdoc) - (*curp->outmdoc)(curp->outdata, mdoc); - -cleanup: - if (*level < rc) - *level = rc; } -static enum mandoclevel +static void passthrough(const char *file, int fd, int synopsis_only) { const char synb[] = "S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS"; @@ -741,12 +836,12 @@ passthrough(const char *file, int fd, int synopsis_only) FILE *stream; const char *syscall; - char *line; - size_t len, off; - ssize_t nw; + char *line, *cp; + size_t linesz; int print; - fflush(stdout); + line = NULL; + linesz = 0; if ((stream = fdopen(fd, "r")) == NULL) { close(fd); @@ -755,48 +850,44 @@ passthrough(const char *file, int fd, int synopsis_only) } print = 0; - while ((line = fgetln(stream, &len)) != NULL) { + while (getline(&line, &linesz, stream) != -1) { + cp = line; if (synopsis_only) { if (print) { - if ( ! isspace((unsigned char)*line)) + if ( ! isspace((unsigned char)*cp)) goto done; - while (len && - isspace((unsigned char)*line)) { - line++; - len--; - } + while (isspace((unsigned char)*cp)) + cp++; } else { - if ((len == sizeof(synb) && - ! strncmp(line, synb, len - 1)) || - (len == sizeof(synr) && - ! strncmp(line, synr, len - 1))) + if (strcmp(cp, synb) == 0 || + strcmp(cp, synr) == 0) print = 1; continue; } } - for (off = 0; off < len; off += nw) - if ((nw = write(STDOUT_FILENO, line + off, - len - off)) == -1 || nw == 0) { - fclose(stream); - syscall = "write"; - goto fail; - } + if (fputs(cp, stdout)) { + fclose(stream); + syscall = "fputs"; + goto fail; + } } if (ferror(stream)) { fclose(stream); - syscall = "fgetln"; + syscall = "getline"; goto fail; } done: + free(line); fclose(stream); - return(MANDOCLEVEL_OK); + return; fail: - fprintf(stderr, "%s: %s: SYSERR: %s: %s", - progname, file, syscall, strerror(errno)); - return(MANDOCLEVEL_SYSERR); + free(line); + warn("%s: SYSERR: %s", file, syscall); + if (rc < MANDOCLEVEL_SYSERR) + rc = MANDOCLEVEL_SYSERR; } static int @@ -812,11 +903,10 @@ koptions(int *options, char *arg) } else if ( ! strcmp(arg, "us-ascii")) { *options &= ~(MPARSE_UTF8 | MPARSE_LATIN1); } else { - fprintf(stderr, "%s: -K %s: Bad argument\n", - progname, arg); - return(0); + warnx("-K %s: Bad argument", arg); + return 0; } - return(1); + return 1; } static int @@ -832,12 +922,11 @@ moptions(int *options, char *arg) else if (0 == strcmp(arg, "an")) *options |= MPARSE_MAN; else { - fprintf(stderr, "%s: -m %s: Bad argument\n", - progname, arg); - return(0); + warnx("-m %s: Bad argument", arg); + return 0; } - return(1); + return 1; } static int @@ -866,12 +955,11 @@ toptions(struct curparse *curp, char *arg) else if (0 == strcmp(arg, "pdf")) curp->outtype = OUTT_PDF; else { - fprintf(stderr, "%s: -T %s: Bad argument\n", - progname, arg); - return(0); + warnx("-T %s: Bad argument", arg); + return 0; } - return(1); + return 1; } static int @@ -895,7 +983,6 @@ woptions(struct curparse *curp, char *arg) curp->wstop = 1; break; case 1: - /* FALLTHROUGH */ case 2: curp->wlevel = MANDOCLEVEL_WARNING; break; @@ -909,13 +996,12 @@ woptions(struct curparse *curp, char *arg) curp->wlevel = MANDOCLEVEL_BADARG; break; default: - fprintf(stderr, "%s: -W %s: Bad argument\n", - progname, o); - return(0); + warnx("-W %s: Bad argument", o); + return 0; } } - return(1); + return 1; } static void @@ -924,7 +1010,8 @@ mmsg(enum mandocerr t, enum mandoclevel lvl, { const char *mparse_msg; - fprintf(stderr, "%s: %s:", progname, file); + fprintf(stderr, "%s: %s:", getprogname(), + file == NULL ? "<stdin>" : file); if (line) fprintf(stderr, "%d:%d:", line, col + 1); @@ -941,55 +1028,22 @@ mmsg(enum mandocerr t, enum mandoclevel lvl, } static pid_t -spawn_pager(void) +spawn_pager(struct tag_files *tag_files) { + const struct timespec timeout = { 0, 100000000 }; /* 0.1s */ #define MAX_PAGER_ARGS 16 char *argv[MAX_PAGER_ARGS]; const char *pager; char *cp; - int fildes[2]; + size_t cmdlen; int argc; pid_t pager_pid; - if (pipe(fildes) == -1) { - fprintf(stderr, "%s: pipe: %s\n", - progname, strerror(errno)); - return(0); - } - - switch (pager_pid = fork()) { - case -1: - fprintf(stderr, "%s: fork: %s\n", - progname, strerror(errno)); - exit((int)MANDOCLEVEL_SYSERR); - case 0: - break; - default: - close(fildes[0]); - if (dup2(fildes[1], STDOUT_FILENO) == -1) { - fprintf(stderr, "%s: dup output: %s\n", - progname, strerror(errno)); - exit((int)MANDOCLEVEL_SYSERR); - } - close(fildes[1]); - return(pager_pid); - } - - /* The child process becomes the pager. */ - - close(fildes[1]); - if (dup2(fildes[0], STDIN_FILENO) == -1) { - fprintf(stderr, "%s: dup input: %s\n", - progname, strerror(errno)); - exit((int)MANDOCLEVEL_SYSERR); - } - close(fildes[0]); - pager = getenv("MANPAGER"); if (pager == NULL || *pager == '\0') pager = getenv("PAGER"); if (pager == NULL || *pager == '\0') - pager = "/usr/bin/more -s"; + pager = "more -s"; cp = mandoc_strdup(pager); /* @@ -998,7 +1052,7 @@ spawn_pager(void) */ argc = 0; - while (argc + 1 < MAX_PAGER_ARGS) { + while (argc + 4 < MAX_PAGER_ARGS) { argv[argc++] = cp; cp = strchr(cp, ' '); if (cp == NULL) @@ -1009,12 +1063,47 @@ spawn_pager(void) if (*cp == '\0') break; } + + /* For less(1), use the tag file. */ + + if ((cmdlen = strlen(argv[0])) >= 4) { + cp = argv[0] + cmdlen - 4; + if (strcmp(cp, "less") == 0) { + argv[argc++] = mandoc_strdup("-T"); + argv[argc++] = tag_files->tfn; + } + } + argv[argc++] = tag_files->ofn; argv[argc] = NULL; - /* Hand over to the pager. */ + switch (pager_pid = fork()) { + case -1: + err((int)MANDOCLEVEL_SYSERR, "fork"); + case 0: + break; + default: + (void)setpgid(pager_pid, 0); + (void)tcsetpgrp(STDIN_FILENO, pager_pid); +#if HAVE_PLEDGE + if (pledge("stdio rpath tmppath tty proc", NULL) == -1) + err((int)MANDOCLEVEL_SYSERR, "pledge"); +#endif + tag_files->pager_pid = pager_pid; + return pager_pid; + } + + /* The child process becomes the pager. */ + + if (dup2(tag_files->ofd, STDOUT_FILENO) == -1) + err((int)MANDOCLEVEL_SYSERR, "pager stdout"); + close(tag_files->ofd); + close(tag_files->tfd); + + /* Do not start the pager before controlling the terminal. */ + + while (tcgetpgrp(STDIN_FILENO) != getpid()) + nanosleep(&timeout, NULL); execvp(argv[0], argv); - fprintf(stderr, "%s: exec: %s\n", - progname, strerror(errno)); - exit((int)MANDOCLEVEL_SYSERR); + err((int)MANDOCLEVEL_SYSERR, "exec %s", argv[0]); } diff --git a/usr/src/cmd/mandoc/main.h b/usr/src/cmd/mandoc/main.h index 9b04a7816a..a53df93c38 100644 --- a/usr/src/cmd/mandoc/main.h +++ b/usr/src/cmd/mandoc/main.h @@ -1,15 +1,15 @@ -/* $Id: main.h,v 1.20 2014/12/31 16:52:40 schwarze Exp $ */ +/* $Id: main.h,v 1.25 2016/07/08 22:29:05 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -18,11 +18,8 @@ #define UNCONST(a) ((void *)(uintptr_t)(const void *)(a)) -__BEGIN_DECLS - -struct mchars; -struct mdoc; -struct man; +struct roff_man; +struct manoutput; /* * Definitions for main.c-visible output device functions, e.g., -Thtml @@ -31,28 +28,26 @@ struct man; * terminal output routines with different character settings. */ -void *html_alloc(const struct mchars *, char *); -void html_mdoc(void *, const struct mdoc *); -void html_man(void *, const struct man *); +void *html_alloc(const struct manoutput *); +void html_mdoc(void *, const struct roff_man *); +void html_man(void *, const struct roff_man *); void html_free(void *); -void tree_mdoc(void *, const struct mdoc *); -void tree_man(void *, const struct man *); +void tree_mdoc(void *, const struct roff_man *); +void tree_man(void *, const struct roff_man *); -void man_mdoc(void *, const struct mdoc *); -void man_man(void *, const struct man *); +void man_mdoc(void *, const struct roff_man *); +void man_man(void *, const struct roff_man *); -void *locale_alloc(const struct mchars *, char *); -void *utf8_alloc(const struct mchars *, char *); -void *ascii_alloc(const struct mchars *, char *); +void *locale_alloc(const struct manoutput *); +void *utf8_alloc(const struct manoutput *); +void *ascii_alloc(const struct manoutput *); void ascii_free(void *); -void ascii_sepline(void *); -void *pdf_alloc(const struct mchars *, char *); -void *ps_alloc(const struct mchars *, char *); +void *pdf_alloc(const struct manoutput *); +void *ps_alloc(const struct manoutput *); void pspdf_free(void *); -void terminal_mdoc(void *, const struct mdoc *); -void terminal_man(void *, const struct man *); - -__END_DECLS +void terminal_mdoc(void *, const struct roff_man *); +void terminal_man(void *, const struct roff_man *); +void terminal_sepline(void *); diff --git a/usr/src/cmd/mandoc/man.c b/usr/src/cmd/mandoc/man.c index 4e7a398d9b..31c094e8d6 100644 --- a/usr/src/cmd/mandoc/man.c +++ b/usr/src/cmd/mandoc/man.c @@ -1,4 +1,4 @@ -/* $Id: man.c,v 1.149 2015/01/30 21:28:46 schwarze Exp $ */ +/* $Id: man.c,v 1.166 2015/10/22 21:54:23 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -8,9 +8,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -27,11 +27,13 @@ #include <stdio.h> #include <string.h> -#include "man.h" -#include "mandoc.h" #include "mandoc_aux.h" -#include "libman.h" +#include "mandoc.h" +#include "roff.h" +#include "man.h" #include "libmandoc.h" +#include "roff_int.h" +#include "libman.h" const char *const __man_macronames[MAN_MAX] = { "br", "TH", "SH", "SS", @@ -48,306 +50,25 @@ const char *const __man_macronames[MAN_MAX] = { const char * const *man_macronames = __man_macronames; -static void man_alloc1(struct man *); -static void man_breakscope(struct man *, enum mant); -static void man_descope(struct man *, int, int); -static void man_free1(struct man *); -static struct man_node *man_node_alloc(struct man *, int, int, - enum man_type, enum mant); -static void man_node_append(struct man *, struct man_node *); -static void man_node_free(struct man_node *); -static void man_node_unlink(struct man *, - struct man_node *); -static int man_ptext(struct man *, int, char *, int); -static int man_pmacro(struct man *, int, char *, int); - - -const struct man_node * -man_node(const struct man *man) -{ - - return(man->first); -} - -const struct man_meta * -man_meta(const struct man *man) -{ - - return(&man->meta); -} - -void -man_reset(struct man *man) -{ - - man_free1(man); - man_alloc1(man); -} - -void -man_free(struct man *man) -{ - - man_free1(man); - free(man); -} - -struct man * -man_alloc(struct roff *roff, struct mparse *parse, - const char *defos, int quick) -{ - struct man *p; - - p = mandoc_calloc(1, sizeof(struct man)); - - man_hash_init(); - p->parse = parse; - p->defos = defos; - p->quick = quick; - p->roff = roff; - - man_alloc1(p); - return(p); -} - -void -man_endparse(struct man *man) -{ +static void man_descope(struct roff_man *, int, int); +static int man_ptext(struct roff_man *, int, char *, int); +static int man_pmacro(struct roff_man *, int, char *, int); - man_macroend(man); -} int -man_parseln(struct man *man, int ln, char *buf, int offs) +man_parseln(struct roff_man *man, int ln, char *buf, int offs) { - if (man->last->type != MAN_EQN || ln > man->last->line) + if (man->last->type != ROFFT_EQN || ln > man->last->line) man->flags |= MAN_NEWLINE; - return (roff_getcontrol(man->roff, buf, &offs) ? + return roff_getcontrol(man->roff, buf, &offs) ? man_pmacro(man, ln, buf, offs) : - man_ptext(man, ln, buf, offs)); -} - -static void -man_free1(struct man *man) -{ - - if (man->first) - man_node_delete(man, man->first); - free(man->meta.title); - free(man->meta.source); - free(man->meta.date); - free(man->meta.vol); - free(man->meta.msec); -} - -static void -man_alloc1(struct man *man) -{ - - memset(&man->meta, 0, sizeof(struct man_meta)); - man->flags = 0; - man->last = mandoc_calloc(1, sizeof(struct man_node)); - man->first = man->last; - man->last->type = MAN_ROOT; - man->last->tok = MAN_MAX; - man->next = MAN_NEXT_CHILD; -} - - -static void -man_node_append(struct man *man, struct man_node *p) -{ - - assert(man->last); - assert(man->first); - assert(p->type != MAN_ROOT); - - switch (man->next) { - case MAN_NEXT_SIBLING: - man->last->next = p; - p->prev = man->last; - p->parent = man->last->parent; - break; - case MAN_NEXT_CHILD: - man->last->child = p; - p->parent = man->last; - break; - default: - abort(); - /* NOTREACHED */ - } - - assert(p->parent); - p->parent->nchild++; - - switch (p->type) { - case MAN_BLOCK: - if (p->tok == MAN_SH || p->tok == MAN_SS) - man->flags &= ~MAN_LITERAL; - break; - case MAN_HEAD: - assert(p->parent->type == MAN_BLOCK); - p->parent->head = p; - break; - case MAN_BODY: - assert(p->parent->type == MAN_BLOCK); - p->parent->body = p; - break; - default: - break; - } - - man->last = p; - - switch (p->type) { - case MAN_TBL: - /* FALLTHROUGH */ - case MAN_TEXT: - man_valid_post(man); - break; - default: - break; - } -} - -static struct man_node * -man_node_alloc(struct man *man, int line, int pos, - enum man_type type, enum mant tok) -{ - struct man_node *p; - - p = mandoc_calloc(1, sizeof(struct man_node)); - p->line = line; - p->pos = pos; - p->type = type; - p->tok = tok; - - if (man->flags & MAN_NEWLINE) - p->flags |= MAN_LINE; - man->flags &= ~MAN_NEWLINE; - return(p); -} - -void -man_elem_alloc(struct man *man, int line, int pos, enum mant tok) -{ - struct man_node *p; - - p = man_node_alloc(man, line, pos, MAN_ELEM, tok); - man_node_append(man, p); - man->next = MAN_NEXT_CHILD; -} - -void -man_head_alloc(struct man *man, int line, int pos, enum mant tok) -{ - struct man_node *p; - - p = man_node_alloc(man, line, pos, MAN_HEAD, tok); - man_node_append(man, p); - man->next = MAN_NEXT_CHILD; -} - -void -man_body_alloc(struct man *man, int line, int pos, enum mant tok) -{ - struct man_node *p; - - p = man_node_alloc(man, line, pos, MAN_BODY, tok); - man_node_append(man, p); - man->next = MAN_NEXT_CHILD; -} - -void -man_block_alloc(struct man *man, int line, int pos, enum mant tok) -{ - struct man_node *p; - - p = man_node_alloc(man, line, pos, MAN_BLOCK, tok); - man_node_append(man, p); - man->next = MAN_NEXT_CHILD; -} - -void -man_word_alloc(struct man *man, int line, int pos, const char *word) -{ - struct man_node *n; - - n = man_node_alloc(man, line, pos, MAN_TEXT, MAN_MAX); - n->string = roff_strdup(man->roff, word); - man_node_append(man, n); - man->next = MAN_NEXT_SIBLING; -} - -void -man_word_append(struct man *man, const char *word) -{ - struct man_node *n; - char *addstr, *newstr; - - n = man->last; - addstr = roff_strdup(man->roff, word); - mandoc_asprintf(&newstr, "%s %s", n->string, addstr); - free(addstr); - free(n->string); - n->string = newstr; - man->next = MAN_NEXT_SIBLING; -} - -/* - * Free all of the resources held by a node. This does NOT unlink a - * node from its context; for that, see man_node_unlink(). - */ -static void -man_node_free(struct man_node *p) -{ - - free(p->string); - free(p); -} - -void -man_node_delete(struct man *man, struct man_node *p) -{ - - while (p->child) - man_node_delete(man, p->child); - - man_node_unlink(man, p); - man_node_free(p); -} - -void -man_addeqn(struct man *man, const struct eqn *ep) -{ - struct man_node *n; - - n = man_node_alloc(man, ep->ln, ep->pos, MAN_EQN, MAN_MAX); - n->eqn = ep; - if (ep->ln > man->last->line) - n->flags |= MAN_LINE; - man_node_append(man, n); - man->next = MAN_NEXT_SIBLING; - man_descope(man, ep->ln, ep->pos); -} - -void -man_addspan(struct man *man, const struct tbl_span *sp) -{ - struct man_node *n; - - man_breakscope(man, MAN_MAX); - n = man_node_alloc(man, sp->line, 0, MAN_TBL, MAN_MAX); - n->span = sp; - man_node_append(man, n); - man->next = MAN_NEXT_SIBLING; - man_descope(man, sp->line, 0); + man_ptext(man, ln, buf, offs); } static void -man_descope(struct man *man, int line, int offs) +man_descope(struct roff_man *man, int line, int offs) { /* * Co-ordinate what happens with having a next-line scope open: @@ -363,20 +84,20 @@ man_descope(struct man *man, int line, int offs) return; man->flags &= ~MAN_BLINE; man_unscope(man, man->last->parent); - man_body_alloc(man, line, offs, man->last->tok); + roff_body_alloc(man, line, offs, man->last->tok); } static int -man_ptext(struct man *man, int line, char *buf, int offs) +man_ptext(struct roff_man *man, int line, char *buf, int offs) { int i; /* Literal free-form text whitespace is preserved. */ if (man->flags & MAN_LITERAL) { - man_word_alloc(man, line, offs, buf + offs); + roff_word_alloc(man, line, offs, buf + offs); man_descope(man, line, offs); - return(1); + return 1; } for (i = offs; buf[i] == ' '; i++) @@ -391,10 +112,10 @@ man_ptext(struct man *man, int line, char *buf, int offs) /* Allocate a blank entry. */ if (man->last->tok != MAN_SH && man->last->tok != MAN_SS) { - man_elem_alloc(man, line, offs, MAN_sp); - man->next = MAN_NEXT_SIBLING; + roff_elem_alloc(man, line, offs, MAN_sp); + man->next = ROFF_NEXT_SIBLING; } - return(1); + return 1; } /* @@ -418,7 +139,7 @@ man_ptext(struct man *man, int line, char *buf, int offs) buf[i] = '\0'; } - man_word_alloc(man, line, offs, buf + offs); + roff_word_alloc(man, line, offs, buf + offs); /* * End-of-sentence check. If the last character is an unescaped @@ -431,15 +152,15 @@ man_ptext(struct man *man, int line, char *buf, int offs) man->last->flags |= MAN_EOS; man_descope(man, line, offs); - return(1); + return 1; } static int -man_pmacro(struct man *man, int ln, char *buf, int offs) +man_pmacro(struct roff_man *man, int ln, char *buf, int offs) { - struct man_node *n; + struct roff_node *n; const char *cp; - enum mant tok; + int tok; int i, ppos; int bline; char mac[5]; @@ -457,12 +178,12 @@ man_pmacro(struct man *man, int ln, char *buf, int offs) mac[i] = '\0'; - tok = (i > 0 && i < 4) ? man_hash_find(mac) : MAN_MAX; + tok = (i > 0 && i < 4) ? man_hash_find(mac) : TOKEN_NONE; - if (tok == MAN_MAX) { + if (tok == TOKEN_NONE) { mandoc_msg(MANDOCERR_MACRO, man->parse, ln, ppos, buf + ppos - 1); - return(1); + return 1; } /* Skip a leading escape sequence or tab. */ @@ -511,9 +232,9 @@ man_pmacro(struct man *man, int ln, char *buf, int offs) if (man->quick && tok == MAN_SH) { n = man->last; - if (n->type == MAN_BODY && + if (n->type == ROFFT_BODY && strcmp(n->prev->child->string, "NAME")) - return(2); + return 2; } /* @@ -524,20 +245,20 @@ man_pmacro(struct man *man, int ln, char *buf, int offs) if ( ! bline || man->flags & MAN_ELINE || man_macros[tok].flags & MAN_NSCOPED) - return(1); + return 1; assert(man->flags & MAN_BLINE); man->flags &= ~MAN_BLINE; man_unscope(man, man->last->parent); - man_body_alloc(man, ln, ppos, man->last->tok); - return(1); + roff_body_alloc(man, ln, ppos, man->last->tok); + return 1; } void -man_breakscope(struct man *man, enum mant tok) +man_breakscope(struct roff_man *man, int tok) { - struct man_node *n; + struct roff_node *n; /* * An element next line scope is open, @@ -545,142 +266,104 @@ man_breakscope(struct man *man, enum mant tok) * Delete the element that is being broken. */ - if (man->flags & MAN_ELINE && (tok == MAN_MAX || + if (man->flags & MAN_ELINE && (tok == TOKEN_NONE || ! (man_macros[tok].flags & MAN_NSCOPED))) { n = man->last; - assert(n->type != MAN_TEXT); + assert(n->type != ROFFT_TEXT); if (man_macros[n->tok].flags & MAN_NSCOPED) n = n->parent; mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line, n->pos, "%s breaks %s", - tok == MAN_MAX ? "TS" : man_macronames[tok], + tok == TOKEN_NONE ? "TS" : man_macronames[tok], man_macronames[n->tok]); - man_node_delete(man, n); + roff_node_delete(man, n); man->flags &= ~MAN_ELINE; } /* + * Weird special case: + * Switching fill mode closes section headers. + */ + + if (man->flags & MAN_BLINE && + (tok == MAN_nf || tok == MAN_fi) && + (man->last->tok == MAN_SH || man->last->tok == MAN_SS)) { + n = man->last; + man_unscope(man, n); + roff_body_alloc(man, n->line, n->pos, n->tok); + man->flags &= ~MAN_BLINE; + } + + /* * A block header next line scope is open, * and the new macro is not allowed inside block headers. * Delete the block that is being broken. */ - if (man->flags & MAN_BLINE && (tok == MAN_MAX || + if (man->flags & MAN_BLINE && (tok == TOKEN_NONE || man_macros[tok].flags & MAN_BSCOPE)) { n = man->last; - if (n->type == MAN_TEXT) + if (n->type == ROFFT_TEXT) n = n->parent; if ( ! (man_macros[n->tok].flags & MAN_BSCOPE)) n = n->parent; - assert(n->type == MAN_HEAD); + assert(n->type == ROFFT_HEAD); n = n->parent; - assert(n->type == MAN_BLOCK); + assert(n->type == ROFFT_BLOCK); assert(man_macros[n->tok].flags & MAN_SCOPED); mandoc_vmsg(MANDOCERR_BLK_LINE, man->parse, n->line, n->pos, "%s breaks %s", - tok == MAN_MAX ? "TS" : man_macronames[tok], + tok == TOKEN_NONE ? "TS" : man_macronames[tok], man_macronames[n->tok]); - man_node_delete(man, n); + roff_node_delete(man, n); man->flags &= ~MAN_BLINE; } } -/* - * Unlink a node from its context. If "man" is provided, the last parse - * point will also be adjusted accordingly. - */ -static void -man_node_unlink(struct man *man, struct man_node *n) -{ - - /* Adjust siblings. */ - - if (n->prev) - n->prev->next = n->next; - if (n->next) - n->next->prev = n->prev; - - /* Adjust parent. */ - - if (n->parent) { - n->parent->nchild--; - if (n->parent->child == n) - n->parent->child = n->prev ? n->prev : n->next; - } - - /* Adjust parse point, if applicable. */ - - if (man && man->last == n) { - /*XXX: this can occur when bailing from validation. */ - /*assert(NULL == n->next);*/ - if (n->prev) { - man->last = n->prev; - man->next = MAN_NEXT_SIBLING; - } else { - man->last = n->parent; - man->next = MAN_NEXT_CHILD; - } - } - - if (man && man->first == n) - man->first = NULL; -} - const struct mparse * -man_mparse(const struct man *man) +man_mparse(const struct roff_man *man) { assert(man && man->parse); - return(man->parse); + return man->parse; } void -man_deroff(char **dest, const struct man_node *n) +man_state(struct roff_man *man, struct roff_node *n) { - char *cp; - size_t sz; - - if (n->type != MAN_TEXT) { - for (n = n->child; n; n = n->next) - man_deroff(dest, n); - return; - } - /* Skip leading whitespace and escape sequences. */ - - cp = n->string; - while ('\0' != *cp) { - if ('\\' == *cp) { - cp++; - mandoc_escape((const char **)&cp, NULL, NULL); - } else if (isspace((unsigned char)*cp)) - cp++; - else - break; + switch(n->tok) { + case MAN_nf: + case MAN_EX: + if (man->flags & MAN_LITERAL && ! (n->flags & MAN_VALID)) + mandoc_msg(MANDOCERR_NF_SKIP, man->parse, + n->line, n->pos, "nf"); + man->flags |= MAN_LITERAL; + break; + case MAN_fi: + case MAN_EE: + if ( ! (man->flags & MAN_LITERAL) && + ! (n->flags & MAN_VALID)) + mandoc_msg(MANDOCERR_FI_SKIP, man->parse, + n->line, n->pos, "fi"); + man->flags &= ~MAN_LITERAL; + break; + default: + break; } + man->last->flags |= MAN_VALID; +} - /* Skip trailing whitespace. */ - - for (sz = strlen(cp); sz; sz--) - if (0 == isspace((unsigned char)cp[sz-1])) - break; - - /* Skip empty strings. */ - - if (0 == sz) - return; - - if (NULL == *dest) { - *dest = mandoc_strndup(cp, sz); - return; - } +void +man_validate(struct roff_man *man) +{ - mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp); - free(*dest); - *dest = cp; + man->last = man->first; + man_node_validate(man); + man->flags &= ~MAN_LITERAL; } diff --git a/usr/src/cmd/mandoc/man.h b/usr/src/cmd/mandoc/man.h index 9e8eb03e57..8f63f3b99e 100644 --- a/usr/src/cmd/mandoc/man.h +++ b/usr/src/cmd/mandoc/man.h @@ -1,116 +1,66 @@ -/* $Id: man.h,v 1.69 2015/01/24 02:41:49 schwarze Exp $ */ +/* $Id: man.h,v 1.77 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -enum mant { - MAN_br = 0, - MAN_TH, - MAN_SH, - MAN_SS, - MAN_TP, - MAN_LP, - MAN_PP, - MAN_P, - MAN_IP, - MAN_HP, - MAN_SM, - MAN_SB, - MAN_BI, - MAN_IB, - MAN_BR, - MAN_RB, - MAN_R, - MAN_B, - MAN_I, - MAN_IR, - MAN_RI, - MAN_sp, - MAN_nf, - MAN_fi, - MAN_RE, - MAN_RS, - MAN_DT, - MAN_UC, - MAN_PD, - MAN_AT, - MAN_in, - MAN_ft, - MAN_OP, - MAN_EX, - MAN_EE, - MAN_UR, - MAN_UE, - MAN_ll, - MAN_MAX -}; +#define MAN_br 0 +#define MAN_TH 1 +#define MAN_SH 2 +#define MAN_SS 3 +#define MAN_TP 4 +#define MAN_LP 5 +#define MAN_PP 6 +#define MAN_P 7 +#define MAN_IP 8 +#define MAN_HP 9 +#define MAN_SM 10 +#define MAN_SB 11 +#define MAN_BI 12 +#define MAN_IB 13 +#define MAN_BR 14 +#define MAN_RB 15 +#define MAN_R 16 +#define MAN_B 17 +#define MAN_I 18 +#define MAN_IR 19 +#define MAN_RI 20 +#define MAN_sp 21 +#define MAN_nf 22 +#define MAN_fi 23 +#define MAN_RE 24 +#define MAN_RS 25 +#define MAN_DT 26 +#define MAN_UC 27 +#define MAN_PD 28 +#define MAN_AT 29 +#define MAN_in 30 +#define MAN_ft 31 +#define MAN_OP 32 +#define MAN_EX 33 +#define MAN_EE 34 +#define MAN_UR 35 +#define MAN_UE 36 +#define MAN_ll 37 +#define MAN_MAX 38 -enum man_type { - MAN_TEXT, - MAN_ELEM, - MAN_ROOT, - MAN_BLOCK, - MAN_HEAD, - MAN_BODY, - MAN_TBL, - MAN_EQN -}; - -struct man_meta { - char *msec; /* `TH' section (1, 3p, etc.) */ - char *date; /* `TH' normalised date */ - char *vol; /* `TH' volume */ - char *title; /* `TH' title (e.g., FOO) */ - char *source; /* `TH' source (e.g., GNU) */ - int hasbody; /* document is not empty */ -}; - -struct man_node { - struct man_node *parent; /* parent AST node */ - struct man_node *child; /* first child AST node */ - struct man_node *next; /* sibling AST node */ - struct man_node *prev; /* prior sibling AST node */ - int nchild; /* number children */ - int line; - int pos; - enum mant tok; /* tok or MAN__MAX if none */ - int flags; -#define MAN_VALID (1 << 0) /* has been validated */ -#define MAN_EOS (1 << 2) /* at sentence boundary */ -#define MAN_LINE (1 << 3) /* first macro/text on line */ - enum man_type type; /* AST node type */ - char *string; /* TEXT node argument */ - struct man_node *head; /* BLOCK node HEAD ptr */ - struct man_node *tail; /* BLOCK node TAIL ptr */ - struct man_node *body; /* BLOCK node BODY ptr */ - const struct tbl_span *span; /* TBL */ - const struct eqn *eqn; /* EQN */ - int aux; /* decoded node data, type-dependent */ -}; - -/* Names of macros. Index is enum mant. */ +/* Names of macros. */ extern const char *const *man_macronames; -__BEGIN_DECLS - -struct man; -const struct man_node *man_node(const struct man *); -const struct man_meta *man_meta(const struct man *); -const struct mparse *man_mparse(const struct man *); -void man_deroff(char **, const struct man_node *); +struct roff_man; -__END_DECLS +const struct mparse *man_mparse(const struct roff_man *); +void man_validate(struct roff_man *); diff --git a/usr/src/cmd/mandoc/man_hash.c b/usr/src/cmd/mandoc/man_hash.c index 1cbfb1b7f8..8573994e5d 100644 --- a/usr/src/cmd/mandoc/man_hash.c +++ b/usr/src/cmd/mandoc/man_hash.c @@ -1,6 +1,7 @@ -/* $Id: man_hash.c,v 1.29 2014/12/01 08:05:52 schwarze Exp $ */ +/* $Id: man_hash.c,v 1.34 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -23,6 +24,7 @@ #include <limits.h> #include <string.h> +#include "roff.h" #include "man.h" #include "libman.h" @@ -46,18 +48,15 @@ static unsigned char table[26 * HASH_DEPTH]; -/* - * XXX - this hash has global scope, so if intended for use as a library - * with multiple callers, it will need re-invocation protection. - */ void man_hash_init(void) { int i, j, x; - memset(table, UCHAR_MAX, sizeof(table)); + if (*table != '\0') + return; - assert(MAN_MAX < UCHAR_MAX); + memset(table, UCHAR_MAX, sizeof(table)); for (i = 0; i < (int)MAN_MAX; i++) { x = man_macronames[i][0]; @@ -76,27 +75,27 @@ man_hash_init(void) } } -enum mant +int man_hash_find(const char *tmp) { int x, y, i; - enum mant tok; + int tok; if ('\0' == (x = tmp[0])) - return(MAN_MAX); + return TOKEN_NONE; if ( ! (isalpha((unsigned char)x))) - return(MAN_MAX); + return TOKEN_NONE; HASH_ROW(x); for (i = 0; i < HASH_DEPTH; i++) { if (UCHAR_MAX == (y = table[x + i])) - return(MAN_MAX); + return TOKEN_NONE; - tok = (enum mant)y; + tok = y; if (0 == strcmp(tmp, man_macronames[tok])) - return(tok); + return tok; } - return(MAN_MAX); + return TOKEN_NONE; } diff --git a/usr/src/cmd/mandoc/man_html.c b/usr/src/cmd/mandoc/man_html.c index 1109415025..d71eb38237 100644 --- a/usr/src/cmd/mandoc/man_html.c +++ b/usr/src/cmd/mandoc/man_html.c @@ -1,4 +1,4 @@ -/* $Id: man_html.c,v 1.112 2015/03/03 21:11:34 schwarze Exp $ */ +/* $Id: man_html.c,v 1.120 2016/01/08 17:48:09 schwarze Exp $ */ /* * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -26,6 +26,7 @@ #include <string.h> #include "mandoc_aux.h" +#include "roff.h" #include "man.h" #include "out.h" #include "html.h" @@ -36,8 +37,8 @@ #define INDENT 5 -#define MAN_ARGS const struct man_meta *man, \ - const struct man_node *n, \ +#define MAN_ARGS const struct roff_meta *man, \ + const struct roff_node *n, \ struct mhtml *mh, \ struct html *h @@ -52,12 +53,11 @@ struct htmlman { }; static void print_bvspace(struct html *, - const struct man_node *); -static void print_man(MAN_ARGS); + const struct roff_node *); static void print_man_head(MAN_ARGS); static void print_man_nodelist(MAN_ARGS); static void print_man_node(MAN_ARGS); -static int a2width(const struct man_node *, +static int a2width(const struct roff_node *, struct roffsu *); static int man_B_pre(MAN_ARGS); static int man_HP_pre(MAN_ARGS); @@ -129,14 +129,14 @@ static const struct htmlman mans[MAN_MAX] = { * first, print it. */ static void -print_bvspace(struct html *h, const struct man_node *n) +print_bvspace(struct html *h, const struct roff_node *n) { if (n->body && n->body->child) - if (MAN_TBL == n->body->child->type) + if (n->body->child->type == ROFFT_TBL) return; - if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) + if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS) if (NULL == n->prev) return; @@ -144,36 +144,31 @@ print_bvspace(struct html *h, const struct man_node *n) } void -html_man(void *arg, const struct man *man) +html_man(void *arg, const struct roff_man *man) { struct mhtml mh; - - memset(&mh, 0, sizeof(struct mhtml)); - print_man(man_meta(man), man_node(man), &mh, (struct html *)arg); - putchar('\n'); -} - -static void -print_man(MAN_ARGS) -{ - struct tag *t, *tt; struct htmlpair tag; + struct html *h; + struct tag *t, *tt; + memset(&mh, 0, sizeof(mh)); PAIR_CLASS_INIT(&tag, "mandoc"); + h = (struct html *)arg; if ( ! (HTML_FRAGMENT & h->oflags)) { print_gen_decls(h); t = print_otag(h, TAG_HTML, 0, NULL); tt = print_otag(h, TAG_HEAD, 0, NULL); - print_man_head(man, n, mh, h); + print_man_head(&man->meta, man->first, &mh, h); print_tagq(h, tt); print_otag(h, TAG_BODY, 0, NULL); print_otag(h, TAG_DIV, 1, &tag); } else t = print_otag(h, TAG_DIV, 1, &tag); - print_man_nodelist(man, n, mh, h); + print_man_nodelist(&man->meta, man->first, &mh, h); print_tagq(h, t); + putchar('\n'); } static void @@ -208,10 +203,10 @@ print_man_node(MAN_ARGS) t = h->tags.head; switch (n->type) { - case MAN_ROOT: + case ROFFT_ROOT: man_root_pre(man, n, mh, h); break; - case MAN_TEXT: + case ROFFT_TEXT: if ('\0' == *n->string) { print_paragraph(h); return; @@ -222,12 +217,12 @@ print_man_node(MAN_ARGS) print_otag(h, TAG_BR, 0, NULL); print_text(h, n->string); return; - case MAN_EQN: + case ROFFT_EQN: if (n->flags & MAN_LINE) putchar('\n'); print_eqn(h, n->eqn); break; - case MAN_TBL: + case ROFFT_TBL: /* * This will take care of initialising all of the table * state data for the first table, then tearing it down @@ -266,10 +261,10 @@ print_man_node(MAN_ARGS) print_stagq(h, t); switch (n->type) { - case MAN_ROOT: + case ROFFT_ROOT: man_root_post(man, n, mh, h); break; - case MAN_EQN: + case ROFFT_EQN: break; default: if (mans[n->tok].post) @@ -279,15 +274,15 @@ print_man_node(MAN_ARGS) } static int -a2width(const struct man_node *n, struct roffsu *su) +a2width(const struct roff_node *n, struct roffsu *su) { - if (MAN_TEXT != n->type) - return(0); + if (n->type != ROFFT_TEXT) + return 0; if (a2roffsu(n->string, su, SCALE_EN)) - return(1); + return 1; - return(0); + return 0; } static void @@ -347,8 +342,8 @@ man_root_post(MAN_ARGS) PAIR_CLASS_INIT(&tag, "foot-os"); print_otag(h, TAG_TD, 1, &tag); - if (man->source) - print_text(h, man->source); + if (man->os) + print_text(h, man->os); print_tagq(h, t); } @@ -376,7 +371,7 @@ man_br_pre(MAN_ARGS) /* So the div isn't empty: */ print_text(h, "\\~"); - return(0); + return 0; } static int @@ -384,22 +379,22 @@ man_SH_pre(MAN_ARGS) { struct htmlpair tag; - if (MAN_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { mh->fl &= ~MANH_LITERAL; PAIR_CLASS_INIT(&tag, "section"); print_otag(h, TAG_DIV, 1, &tag); - return(1); - } else if (MAN_BODY == n->type) - return(1); + return 1; + } else if (n->type == ROFFT_BODY) + return 1; print_otag(h, TAG_H1, 0, NULL); - return(1); + return 1; } static int man_alt_pre(MAN_ARGS) { - const struct man_node *nn; + const struct roff_node *nn; int i, savelit; enum htmltag fp; struct tag *t; @@ -432,7 +427,6 @@ man_alt_pre(MAN_ARGS) break; default: abort(); - /* NOTREACHED */ } if (i) @@ -450,7 +444,7 @@ man_alt_pre(MAN_ARGS) if (savelit) mh->fl |= MANH_LITERAL; - return(0); + return 0; } static int @@ -460,7 +454,7 @@ man_SM_pre(MAN_ARGS) print_otag(h, TAG_SMALL, 0, NULL); if (MAN_SB == n->tok) print_otag(h, TAG_B, 0, NULL); - return(1); + return 1; } static int @@ -468,41 +462,41 @@ man_SS_pre(MAN_ARGS) { struct htmlpair tag; - if (MAN_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { mh->fl &= ~MANH_LITERAL; PAIR_CLASS_INIT(&tag, "subsection"); print_otag(h, TAG_DIV, 1, &tag); - return(1); - } else if (MAN_BODY == n->type) - return(1); + return 1; + } else if (n->type == ROFFT_BODY) + return 1; print_otag(h, TAG_H2, 0, NULL); - return(1); + return 1; } static int man_PP_pre(MAN_ARGS) { - if (MAN_HEAD == n->type) - return(0); - else if (MAN_BLOCK == n->type) + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type == ROFFT_BLOCK) print_bvspace(h, n); - return(1); + return 1; } static int man_IP_pre(MAN_ARGS) { - const struct man_node *nn; + const struct roff_node *nn; - if (MAN_BODY == n->type) { + if (n->type == ROFFT_BODY) { print_otag(h, TAG_DD, 0, NULL); - return(1); - } else if (MAN_HEAD != n->type) { + return 1; + } else if (n->type != ROFFT_HEAD) { print_otag(h, TAG_DL, 0, NULL); - return(1); + return 1; } /* FIXME: width specification. */ @@ -526,7 +520,7 @@ man_IP_pre(MAN_ARGS) } } - return(0); + return 0; } static int @@ -534,12 +528,12 @@ man_HP_pre(MAN_ARGS) { struct htmlpair tag[2]; struct roffsu su; - const struct man_node *np; + const struct roff_node *np; - if (MAN_HEAD == n->type) - return(0); - else if (MAN_BLOCK != n->type) - return(1); + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type != ROFFT_BLOCK) + return 1; np = n->head->child; @@ -555,7 +549,7 @@ man_HP_pre(MAN_ARGS) PAIR_STYLE_INIT(&tag[0], h); PAIR_CLASS_INIT(&tag[1], "spacer"); print_otag(h, TAG_DIV, 2, tag); - return(1); + return 1; } static int @@ -584,7 +578,7 @@ man_OP_pre(MAN_ARGS) print_stagq(h, tt); h->flags |= HTML_NOSPACE; print_text(h, "]"); - return(0); + return 0; } static int @@ -592,7 +586,7 @@ man_B_pre(MAN_ARGS) { print_otag(h, TAG_B, 0, NULL); - return(1); + return 1; } static int @@ -600,7 +594,7 @@ man_I_pre(MAN_ARGS) { print_otag(h, TAG_I, 0, NULL); - return(1); + return 1; } static int @@ -613,7 +607,7 @@ man_literal_pre(MAN_ARGS) } else mh->fl |= MANH_LITERAL; - return(0); + return 0; } static int @@ -621,14 +615,14 @@ man_in_pre(MAN_ARGS) { print_otag(h, TAG_BR, 0, NULL); - return(0); + return 0; } static int man_ign_pre(MAN_ARGS) { - return(0); + return 0; } static int @@ -637,10 +631,10 @@ man_RS_pre(MAN_ARGS) struct htmlpair tag; struct roffsu su; - if (MAN_HEAD == n->type) - return(0); - else if (MAN_BODY == n->type) - return(1); + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type == ROFFT_BODY) + return 1; SCALE_HS_INIT(&su, INDENT); if (n->head->child) @@ -650,7 +644,7 @@ man_RS_pre(MAN_ARGS) bufcat_su(h, "margin-left", &su); PAIR_STYLE_INIT(&tag, h); print_otag(h, TAG_DIV, 1, &tag); - return(1); + return 1; } static int @@ -659,19 +653,19 @@ man_UR_pre(MAN_ARGS) struct htmlpair tag[2]; n = n->child; - assert(MAN_HEAD == n->type); - if (n->nchild) { - assert(MAN_TEXT == n->child->type); + assert(n->type == ROFFT_HEAD); + if (n->child != NULL) { + assert(n->child->type == ROFFT_TEXT); PAIR_CLASS_INIT(&tag[0], "link-ext"); PAIR_HREF_INIT(&tag[1], n->child->string); print_otag(h, TAG_A, 2, tag); } - assert(MAN_BODY == n->next->type); - if (n->next->nchild) + assert(n->next->type == ROFFT_BODY); + if (n->next->child != NULL) n = n->next; print_man_nodelist(man, n->child, mh, h); - return(0); + return 0; } diff --git a/usr/src/cmd/mandoc/man_macro.c b/usr/src/cmd/mandoc/man_macro.c index c86ab6f13f..d15335709e 100644 --- a/usr/src/cmd/mandoc/man_macro.c +++ b/usr/src/cmd/mandoc/man_macro.c @@ -1,4 +1,4 @@ -/* $Id: man_macro.c,v 1.98 2015/02/06 11:54:36 schwarze Exp $ */ +/* $Id: man_macro.c,v 1.114 2016/01/08 17:48:09 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2012, 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -8,9 +8,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -25,37 +25,27 @@ #include <stdlib.h> #include <string.h> -#include "man.h" #include "mandoc.h" +#include "roff.h" +#include "man.h" #include "libmandoc.h" +#include "roff_int.h" #include "libman.h" -enum rew { - REW_REWIND, - REW_NOHALT, - REW_HALT -}; - static void blk_close(MACRO_PROT_ARGS); static void blk_exp(MACRO_PROT_ARGS); static void blk_imp(MACRO_PROT_ARGS); static void in_line_eoln(MACRO_PROT_ARGS); -static int man_args(struct man *, int, +static int man_args(struct roff_man *, int, int *, char *, char **); - -static void rew_scope(enum man_type, - struct man *, enum mant); -static enum rew rew_dohalt(enum mant, enum man_type, - const struct man_node *); -static enum rew rew_block(enum mant, enum man_type, - const struct man_node *); +static void rew_scope(struct roff_man *, int); const struct man_macro __man_macros[MAN_MAX] = { { in_line_eoln, MAN_NSCOPED }, /* br */ { in_line_eoln, MAN_BSCOPE }, /* TH */ { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SH */ { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* SS */ - { blk_imp, MAN_BSCOPE | MAN_SCOPED | MAN_FSCOPED }, /* TP */ + { blk_imp, MAN_BSCOPE | MAN_SCOPED }, /* TP */ { blk_imp, MAN_BSCOPE }, /* LP */ { blk_imp, MAN_BSCOPE }, /* PP */ { blk_imp, MAN_BSCOPE }, /* P */ @@ -73,20 +63,20 @@ const struct man_macro __man_macros[MAN_MAX] = { { in_line_eoln, 0 }, /* IR */ { in_line_eoln, 0 }, /* RI */ { in_line_eoln, MAN_NSCOPED }, /* sp */ - { in_line_eoln, MAN_BSCOPE }, /* nf */ - { in_line_eoln, MAN_BSCOPE }, /* fi */ + { in_line_eoln, MAN_NSCOPED }, /* nf */ + { in_line_eoln, MAN_NSCOPED }, /* fi */ { blk_close, MAN_BSCOPE }, /* RE */ - { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* RS */ + { blk_exp, MAN_BSCOPE }, /* RS */ { in_line_eoln, 0 }, /* DT */ { in_line_eoln, 0 }, /* UC */ - { in_line_eoln, 0 }, /* PD */ + { in_line_eoln, MAN_NSCOPED }, /* PD */ { in_line_eoln, 0 }, /* AT */ { in_line_eoln, 0 }, /* in */ { in_line_eoln, 0 }, /* ft */ { in_line_eoln, 0 }, /* OP */ { in_line_eoln, MAN_BSCOPE }, /* EX */ { in_line_eoln, MAN_BSCOPE }, /* EE */ - { blk_exp, MAN_BSCOPE | MAN_EXPLICIT }, /* UR */ + { blk_exp, MAN_BSCOPE }, /* UR */ { blk_close, MAN_BSCOPE }, /* UE */ { in_line_eoln, 0 }, /* ll */ }; @@ -95,9 +85,9 @@ const struct man_macro * const man_macros = __man_macros; void -man_unscope(struct man *man, const struct man_node *to) +man_unscope(struct roff_man *man, const struct roff_node *to) { - struct man_node *n; + struct roff_node *n; to = to->parent; n = man->last; @@ -115,17 +105,17 @@ man_unscope(struct man *man, const struct man_node *to) if (man->flags & MAN_ELINE) man->flags &= ~MAN_ELINE; else { - assert(n->type == MAN_HEAD); + assert(n->type == ROFFT_HEAD); n = n->parent; man->flags &= ~MAN_BLINE; } man->last = n; n = n->parent; - man_node_delete(man, man->last); + roff_node_delete(man, man->last); continue; } - if (n->type == MAN_BLOCK && - man_macros[n->tok].flags & MAN_EXPLICIT) + if (n->type == ROFFT_BLOCK && + man_macros[n->tok].fp == blk_exp) mandoc_msg(MANDOCERR_BLK_NOEND, man->parse, n->line, n->pos, man_macronames[n->tok]); @@ -140,7 +130,7 @@ man_unscope(struct man *man, const struct man_node *to) man->last = n; n = n->parent; - man_valid_post(man); + man->last->flags |= MAN_VALID; } /* @@ -151,90 +141,7 @@ man_unscope(struct man *man, const struct man_node *to) */ man->next = (man->last == to) ? - MAN_NEXT_CHILD : MAN_NEXT_SIBLING; -} - -static enum rew -rew_block(enum mant ntok, enum man_type type, const struct man_node *n) -{ - - if (type == MAN_BLOCK && ntok == n->parent->tok && - n->parent->type == MAN_BODY) - return(REW_REWIND); - return(ntok == n->tok ? REW_HALT : REW_NOHALT); -} - -/* - * There are three scope levels: scoped to the root (all), scoped to the - * section (all less sections), and scoped to subsections (all less - * sections and subsections). - */ -static enum rew -rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n) -{ - enum rew c; - - /* We cannot progress beyond the root ever. */ - if (MAN_ROOT == n->type) - return(REW_HALT); - - assert(n->parent); - - /* Normal nodes shouldn't go to the level of the root. */ - if (MAN_ROOT == n->parent->type) - return(REW_REWIND); - - /* Already-validated nodes should be closed out. */ - if (MAN_VALID & n->flags) - return(REW_NOHALT); - - /* First: rewind to ourselves. */ - if (type == n->type && tok == n->tok) { - if (MAN_EXPLICIT & man_macros[n->tok].flags) - return(REW_HALT); - else - return(REW_REWIND); - } - - /* - * Next follow the implicit scope-smashings as defined by man.7: - * section, sub-section, etc. - */ - - switch (tok) { - case MAN_SH: - break; - case MAN_SS: - /* Rewind to a section, if a block. */ - if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) - return(c); - break; - case MAN_RS: - /* Preserve empty paragraphs before RS. */ - if (0 == n->nchild && (MAN_P == n->tok || - MAN_PP == n->tok || MAN_LP == n->tok)) - return(REW_HALT); - /* Rewind to a subsection, if a block. */ - if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) - return(c); - /* Rewind to a section, if a block. */ - if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) - return(c); - break; - default: - /* Rewind to an offsetter, if a block. */ - if (REW_NOHALT != (c = rew_block(MAN_RS, type, n))) - return(c); - /* Rewind to a subsection, if a block. */ - if (REW_NOHALT != (c = rew_block(MAN_SS, type, n))) - return(c); - /* Rewind to a section, if a block. */ - if (REW_NOHALT != (c = rew_block(MAN_SH, type, n))) - return(c); - break; - } - - return(REW_NOHALT); + ROFF_NEXT_CHILD : ROFF_NEXT_SIBLING; } /* @@ -243,30 +150,40 @@ rew_dohalt(enum mant tok, enum man_type type, const struct man_node *n) * scopes. When a scope is closed, it must be validated and actioned. */ static void -rew_scope(enum man_type type, struct man *man, enum mant tok) +rew_scope(struct roff_man *man, int tok) { - struct man_node *n; - enum rew c; + struct roff_node *n; - for (n = man->last; n; n = n->parent) { - /* - * Whether we should stop immediately (REW_HALT), stop - * and rewind until this point (REW_REWIND), or keep - * rewinding (REW_NOHALT). - */ - c = rew_dohalt(tok, type, n); - if (REW_HALT == c) - return; - if (REW_REWIND == c) - break; - } + /* Preserve empty paragraphs before RS. */ - /* - * Rewind until the current point. Warn if we're a roff - * instruction that's mowing over explicit scopes. - */ + n = man->last; + if (tok == MAN_RS && n->child == NULL && + (n->tok == MAN_P || n->tok == MAN_PP || n->tok == MAN_LP)) + return; - man_unscope(man, n); + for (;;) { + if (n->type == ROFFT_ROOT) + return; + if (n->flags & MAN_VALID) { + n = n->parent; + continue; + } + if (n->type != ROFFT_BLOCK) { + if (n->parent->type == ROFFT_ROOT) { + man_unscope(man, n); + return; + } else { + n = n->parent; + continue; + } + } + if (tok != MAN_SH && (n->tok == MAN_SH || + (tok != MAN_SS && (n->tok == MAN_SS || + man_macros[n->tok].fp == blk_exp)))) + return; + man_unscope(man, n); + n = man->last; + } } @@ -276,8 +193,8 @@ rew_scope(enum man_type type, struct man *man, enum mant tok) void blk_close(MACRO_PROT_ARGS) { - enum mant ntok; - const struct man_node *nn; + int ntok; + const struct roff_node *nn; char *p; int nrew, target; @@ -288,7 +205,7 @@ blk_close(MACRO_PROT_ARGS) if ( ! man_args(man, line, pos, buf, &p)) break; for (nn = man->last->parent; nn; nn = nn->parent) - if (nn->tok == ntok && nn->type == MAN_BLOCK) + if (nn->tok == ntok && nn->type == ROFFT_BLOCK) nrew++; target = strtol(p, &p, 10); if (*p != '\0') @@ -308,17 +225,16 @@ blk_close(MACRO_PROT_ARGS) break; default: abort(); - /* NOTREACHED */ } for (nn = man->last->parent; nn; nn = nn->parent) - if (nn->tok == ntok && nn->type == MAN_BLOCK && ! --nrew) + if (nn->tok == ntok && nn->type == ROFFT_BLOCK && ! --nrew) break; if (nn == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, man->parse, line, ppos, man_macronames[tok]); - rew_scope(MAN_BLOCK, man, MAN_PP); + rew_scope(man, MAN_PP); } else { line = man->last->line; ppos = man->last->pos; @@ -337,18 +253,17 @@ blk_close(MACRO_PROT_ARGS) void blk_exp(MACRO_PROT_ARGS) { - struct man_node *head; + struct roff_node *head; char *p; int la; - rew_scope(MAN_BLOCK, man, tok); - man_block_alloc(man, line, ppos, tok); - man_head_alloc(man, line, ppos, tok); - head = man->last; + rew_scope(man, tok); + roff_block_alloc(man, line, ppos, tok); + head = roff_head_alloc(man, line, ppos, tok); la = *pos; if (man_args(man, line, pos, buf, &p)) - man_word_alloc(man, line, la, p); + roff_word_alloc(man, line, la, p); if (buf[*pos] != '\0') mandoc_vmsg(MANDOCERR_ARG_EXCESS, @@ -356,12 +271,12 @@ blk_exp(MACRO_PROT_ARGS) man_macronames[tok], buf + *pos); man_unscope(man, head); - man_body_alloc(man, line, ppos, tok); + roff_body_alloc(man, line, ppos, tok); } /* - * Parse an implicit-block macro. These contain a MAN_HEAD and a - * MAN_BODY contained within a MAN_BLOCK. Rules for closing out other + * Parse an implicit-block macro. These contain a ROFFT_HEAD and a + * ROFFT_BODY contained within a ROFFT_BLOCK. Rules for closing out other * scopes, such as `SH' closing out an `SS', are defined in the rew * routines. */ @@ -370,13 +285,13 @@ blk_imp(MACRO_PROT_ARGS) { int la; char *p; - struct man_node *n; + struct roff_node *n; - rew_scope(MAN_BODY, man, tok); - rew_scope(MAN_BLOCK, man, tok); - man_block_alloc(man, line, ppos, tok); - man_head_alloc(man, line, ppos, tok); - n = man->last; + rew_scope(man, tok); + n = roff_block_alloc(man, line, ppos, tok); + if (n->tok == MAN_SH || n->tok == MAN_SS) + man->flags &= ~MAN_LITERAL; + n = roff_head_alloc(man, line, ppos, tok); /* Add line arguments. */ @@ -384,23 +299,25 @@ blk_imp(MACRO_PROT_ARGS) la = *pos; if ( ! man_args(man, line, pos, buf, &p)) break; - man_word_alloc(man, line, la, p); + roff_word_alloc(man, line, la, p); } - /* Close out head and open body (unless MAN_SCOPE). */ + /* + * For macros having optional next-line scope, + * keep the head open if there were no arguments. + * For `TP', always keep the head open. + */ - if (man_macros[tok].flags & MAN_SCOPED) { - /* If we're forcing scope (`TP'), keep it open. */ - if (man_macros[tok].flags & MAN_FSCOPED) { - man->flags |= MAN_BLINE; - return; - } else if (n == man->last) { - man->flags |= MAN_BLINE; - return; - } + if (man_macros[tok].flags & MAN_SCOPED && + (tok == MAN_TP || n == man->last)) { + man->flags |= MAN_BLINE; + return; } - rew_scope(MAN_HEAD, man, tok); - man_body_alloc(man, line, ppos, tok); + + /* Close out the head and open the body. */ + + man_unscope(man, n); + roff_body_alloc(man, line, ppos, tok); } void @@ -408,9 +325,9 @@ in_line_eoln(MACRO_PROT_ARGS) { int la; char *p; - struct man_node *n; + struct roff_node *n; - man_elem_alloc(man, line, ppos, tok); + roff_elem_alloc(man, line, ppos, tok); n = man->last; for (;;) { @@ -432,10 +349,10 @@ in_line_eoln(MACRO_PROT_ARGS) if ( ! man_args(man, line, pos, buf, &p)) break; if (man_macros[tok].flags & MAN_JOIN && - man->last->type == MAN_TEXT) - man_word_append(man, p); + man->last->type == ROFFT_TEXT) + roff_word_append(man, p); else - man_word_alloc(man, line, la, p); + roff_word_alloc(man, line, la, p); } /* @@ -459,43 +376,28 @@ in_line_eoln(MACRO_PROT_ARGS) return; } - assert(man->last->type != MAN_ROOT); - man->next = MAN_NEXT_SIBLING; + assert(man->last->type != ROFFT_ROOT); + man->next = ROFF_NEXT_SIBLING; - /* - * Rewind our element scope. Note that when TH is pruned, we'll - * be back at the root, so make sure that we don't clobber as - * its sibling. - */ + /* Rewind our element scope. */ for ( ; man->last; man->last = man->last->parent) { + man_state(man, man->last); if (man->last == n) break; - if (man->last->type == MAN_ROOT) - break; - man_valid_post(man); } - - assert(man->last); - - /* - * Same here regarding whether we're back at the root. - */ - - if (man->last->type != MAN_ROOT) - man_valid_post(man); } - void -man_macroend(struct man *man) +man_endparse(struct roff_man *man) { man_unscope(man, man->first); + man->flags &= ~MAN_LITERAL; } static int -man_args(struct man *man, int line, int *pos, char *buf, char **v) +man_args(struct roff_man *man, int line, int *pos, char *buf, char **v) { char *start; @@ -504,8 +406,8 @@ man_args(struct man *man, int line, int *pos, char *buf, char **v) assert(' ' != *start); if ('\0' == *start) - return(0); + return 0; *v = mandoc_getarg(man->parse, v, line, pos); - return(1); + return 1; } diff --git a/usr/src/cmd/mandoc/man_term.c b/usr/src/cmd/mandoc/man_term.c index 8be7927a65..f45e24afea 100644 --- a/usr/src/cmd/mandoc/man_term.c +++ b/usr/src/cmd/mandoc/man_term.c @@ -1,4 +1,4 @@ -/* $Id: man_term.c,v 1.169 2015/03/06 15:48:52 schwarze Exp $ */ +/* $Id: man_term.c,v 1.187 2016/01/08 17:48:09 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -26,10 +26,11 @@ #include <stdlib.h> #include <string.h> -#include "mandoc.h" #include "mandoc_aux.h" -#include "out.h" +#include "mandoc.h" +#include "roff.h" #include "man.h" +#include "out.h" #include "term.h" #include "main.h" @@ -47,8 +48,8 @@ struct mtermp { #define DECL_ARGS struct termp *p, \ struct mtermp *mt, \ - struct man_node *n, \ - const struct man_meta *meta + struct roff_node *n, \ + const struct roff_meta *meta struct termact { int (*pre)(DECL_ARGS); @@ -59,10 +60,12 @@ struct termact { static void print_man_nodelist(DECL_ARGS); static void print_man_node(DECL_ARGS); -static void print_man_head(struct termp *, const void *); -static void print_man_foot(struct termp *, const void *); +static void print_man_head(struct termp *, + const struct roff_meta *); +static void print_man_foot(struct termp *, + const struct roff_meta *); static void print_bvspace(struct termp *, - const struct man_node *, int); + const struct roff_node *, int); static int pre_B(DECL_ARGS); static int pre_HP(DECL_ARGS); @@ -135,36 +138,32 @@ static const struct termact termacts[MAN_MAX] = { void -terminal_man(void *arg, const struct man *man) +terminal_man(void *arg, const struct roff_man *man) { struct termp *p; - const struct man_meta *meta; - struct man_node *n; + struct roff_node *n; struct mtermp mt; p = (struct termp *)arg; - p->overstep = 0; p->rmargin = p->maxrmargin = p->defrmargin; p->tabwidth = term_len(p, 5); - n = man_node(man)->child; - meta = man_meta(man); - memset(&mt, 0, sizeof(struct mtermp)); - mt.lmargin[mt.lmargincur] = term_len(p, p->defindent); mt.offset = term_len(p, p->defindent); mt.pardist = 1; + n = man->first->child; if (p->synopsisonly) { while (n != NULL) { if (n->tok == MAN_SH && - n->child->child->type == MAN_TEXT && + n->child->child->type == ROFFT_TEXT && !strcmp(n->child->child->string, "SYNOPSIS")) { if (n->child->next->child != NULL) print_man_nodelist(p, &mt, - n->child->next->child, meta); + n->child->next->child, + &man->meta); term_newln(p); break; } @@ -173,10 +172,10 @@ terminal_man(void *arg, const struct man *man) } else { if (p->defindent == 0) p->defindent = 7; - term_begin(p, print_man_head, print_man_foot, meta); + term_begin(p, print_man_head, print_man_foot, &man->meta); p->flags |= TERMP_NOSPACE; if (n != NULL) - print_man_nodelist(p, &mt, n, meta); + print_man_nodelist(p, &mt, n, &man->meta); term_end(p); } } @@ -190,17 +189,17 @@ terminal_man(void *arg, const struct man *man) * first, print it. */ static void -print_bvspace(struct termp *p, const struct man_node *n, int pardist) +print_bvspace(struct termp *p, const struct roff_node *n, int pardist) { int i; term_newln(p); if (n->body && n->body->child) - if (MAN_TBL == n->body->child->type) + if (n->body->child->type == ROFFT_TBL) return; - if (MAN_ROOT == n->parent->type || MAN_RS != n->parent->tok) + if (n->parent->type == ROFFT_ROOT || n->parent->tok != MAN_RS) if (NULL == n->prev) return; @@ -213,15 +212,15 @@ static int pre_ign(DECL_ARGS) { - return(0); + return 0; } static int pre_ll(DECL_ARGS) { - term_setwidth(p, n->nchild ? n->child->string : NULL); - return(0); + term_setwidth(p, n->child != NULL ? n->child->string : NULL); + return 0; } static int @@ -229,7 +228,7 @@ pre_I(DECL_ARGS) { term_fontrepl(p, TERMFONT_UNDER); - return(1); + return 1; } static int @@ -256,7 +255,7 @@ pre_literal(DECL_ARGS) p->flags |= TERMP_NOSPACE; } - return(0); + return 0; } static int @@ -267,19 +266,19 @@ pre_PD(DECL_ARGS) n = n->child; if (n == NULL) { mt->pardist = 1; - return(0); + return 0; } - assert(MAN_TEXT == n->type); + assert(n->type == ROFFT_TEXT); if (a2roffsu(n->string, &su, SCALE_VS)) mt->pardist = term_vspan(p, &su); - return(0); + return 0; } static int pre_alternate(DECL_ARGS) { enum termfont font[2]; - struct man_node *nn; + struct roff_node *nn; int savelit, i; switch (n->tok) { @@ -318,12 +317,15 @@ pre_alternate(DECL_ARGS) term_fontrepl(p, font[i]); if (savelit && NULL == nn->next) mt->fl |= MANT_LITERAL; - print_man_node(p, mt, nn, meta); + assert(nn->type == ROFFT_TEXT); + term_word(p, nn->string); + if (nn->flags & MAN_EOS) + p->flags |= TERMP_SENTENCE; if (nn->next) p->flags |= TERMP_NOSPACE; } - return(0); + return 0; } static int @@ -331,7 +333,7 @@ pre_B(DECL_ARGS) { term_fontrepl(p, TERMFONT_BOLD); - return(1); + return 1; } static int @@ -353,7 +355,7 @@ pre_OP(DECL_ARGS) term_fontrepl(p, TERMFONT_NONE); p->flags |= TERMP_NOSPACE; term_word(p, "]"); - return(0); + return 0; } static int @@ -363,20 +365,17 @@ pre_ft(DECL_ARGS) if (NULL == n->child) { term_fontlast(p); - return(0); + return 0; } cp = n->child->string; switch (*cp) { case '4': - /* FALLTHROUGH */ case '3': - /* FALLTHROUGH */ case 'B': term_fontrepl(p, TERMFONT_BOLD); break; case '2': - /* FALLTHROUGH */ case 'I': term_fontrepl(p, TERMFONT_UNDER); break; @@ -384,16 +383,14 @@ pre_ft(DECL_ARGS) term_fontlast(p); break; case '1': - /* FALLTHROUGH */ case 'C': - /* FALLTHROUGH */ case 'R': term_fontrepl(p, TERMFONT_NONE); break; default: break; } - return(0); + return 0; } static int @@ -408,7 +405,7 @@ pre_in(DECL_ARGS) if (NULL == n->child) { p->offset = mt->offset; - return(0); + return 0; } cp = n->child->string; @@ -422,9 +419,9 @@ pre_in(DECL_ARGS) cp--; if ( ! a2roffsu(++cp, &su, SCALE_EN)) - return(0); + return 0; - v = term_hspan(p, &su); + v = (term_hspan(p, &su) + 11) / 24; if (less < 0) p->offset -= p->offset > v ? v : p->offset; @@ -435,7 +432,7 @@ pre_in(DECL_ARGS) if (p->offset > SHRT_MAX) p->offset = term_len(p, p->defindent); - return(0); + return 0; } static int @@ -447,16 +444,11 @@ pre_sp(DECL_ARGS) if ((NULL == n->prev && n->parent)) { switch (n->parent->tok) { case MAN_SH: - /* FALLTHROUGH */ case MAN_SS: - /* FALLTHROUGH */ case MAN_PP: - /* FALLTHROUGH */ case MAN_LP: - /* FALLTHROUGH */ case MAN_P: - /* FALLTHROUGH */ - return(0); + return 0; default: break; } @@ -480,24 +472,35 @@ pre_sp(DECL_ARGS) for (i = 0; i < len; i++) term_vspace(p); - return(0); + /* + * Handle an explicit break request in the same way + * as an overflowing line. + */ + + if (p->flags & TERMP_BRIND) { + p->offset = p->rmargin; + p->rmargin = p->maxrmargin; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); + } + + return 0; } static int pre_HP(DECL_ARGS) { struct roffsu su; - const struct man_node *nn; + const struct roff_node *nn; int len; switch (n->type) { - case MAN_BLOCK: + case ROFFT_BLOCK: print_bvspace(p, n, mt->pardist); - return(1); - case MAN_BODY: + return 1; + case ROFFT_BODY: break; default: - return(0); + return 0; } if ( ! (MANT_LITERAL & mt->fl)) { @@ -509,7 +512,7 @@ pre_HP(DECL_ARGS) if ((nn = n->parent->head->child) != NULL && a2roffsu(nn->string, &su, SCALE_EN)) { - len = term_hspan(p, &su); + len = term_hspan(p, &su) / 24; if (len < 0 && (size_t)(-len) > mt->offset) len = -mt->offset; else if (len > SHRT_MAX) @@ -520,7 +523,7 @@ pre_HP(DECL_ARGS) p->offset = mt->offset; p->rmargin = mt->offset + len; - return(1); + return 1; } static void @@ -528,8 +531,19 @@ post_HP(DECL_ARGS) { switch (n->type) { - case MAN_BODY: + case ROFFT_BODY: term_newln(p); + + /* + * Compatibility with a groff bug. + * The .HP macro uses the undocumented .tag request + * which causes a line break and cancels no-space + * mode even if there isn't any output. + */ + + if (n->child == NULL) + term_vspace(p); + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); p->trailspace = 0; p->offset = mt->offset; @@ -545,7 +559,7 @@ pre_PP(DECL_ARGS) { switch (n->type) { - case MAN_BLOCK: + case ROFFT_BLOCK: mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); print_bvspace(p, n, mt->pardist); break; @@ -554,36 +568,36 @@ pre_PP(DECL_ARGS) break; } - return(MAN_HEAD != n->type); + return n->type != ROFFT_HEAD; } static int pre_IP(DECL_ARGS) { struct roffsu su; - const struct man_node *nn; + const struct roff_node *nn; int len, savelit; switch (n->type) { - case MAN_BODY: + case ROFFT_BODY: p->flags |= TERMP_NOSPACE; break; - case MAN_HEAD: + case ROFFT_HEAD: p->flags |= TERMP_NOBREAK; p->trailspace = 1; break; - case MAN_BLOCK: + case ROFFT_BLOCK: print_bvspace(p, n, mt->pardist); /* FALLTHROUGH */ default: - return(1); + return 1; } /* Calculate the offset from the optional second argument. */ if ((nn = n->parent->head->child) != NULL && (nn = nn->next) != NULL && a2roffsu(nn->string, &su, SCALE_EN)) { - len = term_hspan(p, &su); + len = term_hspan(p, &su) / 24; if (len < 0 && (size_t)(-len) > mt->offset) len = -mt->offset; else if (len > SHRT_MAX) @@ -593,7 +607,7 @@ pre_IP(DECL_ARGS) len = mt->lmargin[mt->lmargincur]; switch (n->type) { - case MAN_HEAD: + case ROFFT_HEAD: p->offset = mt->offset; p->rmargin = mt->offset + len; @@ -606,8 +620,8 @@ pre_IP(DECL_ARGS) if (savelit) mt->fl |= MANT_LITERAL; - return(0); - case MAN_BODY: + return 0; + case ROFFT_BODY: p->offset = mt->offset + len; p->rmargin = p->maxrmargin; break; @@ -615,7 +629,7 @@ pre_IP(DECL_ARGS) break; } - return(1); + return 1; } static void @@ -623,13 +637,13 @@ post_IP(DECL_ARGS) { switch (n->type) { - case MAN_HEAD: + case ROFFT_HEAD: term_flushln(p); p->flags &= ~TERMP_NOBREAK; p->trailspace = 0; p->rmargin = p->maxrmargin; break; - case MAN_BODY: + case ROFFT_BODY: term_newln(p); p->offset = mt->offset; break; @@ -642,22 +656,22 @@ static int pre_TP(DECL_ARGS) { struct roffsu su; - struct man_node *nn; + struct roff_node *nn; int len, savelit; switch (n->type) { - case MAN_HEAD: - p->flags |= TERMP_NOBREAK; + case ROFFT_HEAD: + p->flags |= TERMP_NOBREAK | TERMP_BRTRSP; p->trailspace = 1; break; - case MAN_BODY: + case ROFFT_BODY: p->flags |= TERMP_NOSPACE; break; - case MAN_BLOCK: + case ROFFT_BLOCK: print_bvspace(p, n, mt->pardist); /* FALLTHROUGH */ default: - return(1); + return 1; } /* Calculate offset. */ @@ -665,7 +679,7 @@ pre_TP(DECL_ARGS) if ((nn = n->parent->head->child) != NULL && nn->string != NULL && ! (MAN_LINE & nn->flags) && a2roffsu(nn->string, &su, SCALE_EN)) { - len = term_hspan(p, &su); + len = term_hspan(p, &su) / 24; if (len < 0 && (size_t)(-len) > mt->offset) len = -mt->offset; else if (len > SHRT_MAX) @@ -675,7 +689,7 @@ pre_TP(DECL_ARGS) len = mt->lmargin[mt->lmargincur]; switch (n->type) { - case MAN_HEAD: + case ROFFT_HEAD: p->offset = mt->offset; p->rmargin = mt->offset + len; @@ -694,18 +708,18 @@ pre_TP(DECL_ARGS) if (savelit) mt->fl |= MANT_LITERAL; - return(0); - case MAN_BODY: + return 0; + case ROFFT_BODY: p->offset = mt->offset + len; p->rmargin = p->maxrmargin; p->trailspace = 0; - p->flags &= ~TERMP_NOBREAK; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP); break; default: break; } - return(1); + return 1; } static void @@ -713,10 +727,10 @@ post_TP(DECL_ARGS) { switch (n->type) { - case MAN_HEAD: + case ROFFT_HEAD: term_flushln(p); break; - case MAN_BODY: + case ROFFT_BODY: term_newln(p); p->offset = mt->offset; break; @@ -731,7 +745,7 @@ pre_SS(DECL_ARGS) int i; switch (n->type) { - case MAN_BLOCK: + case ROFFT_BLOCK: mt->fl &= ~MANT_LITERAL; mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->offset = term_len(p, p->defindent); @@ -743,25 +757,32 @@ pre_SS(DECL_ARGS) do { n = n->prev; - } while (n != NULL && termacts[n->tok].flags & MAN_NOTEXT); + } while (n != NULL && n->tok != TOKEN_NONE && + termacts[n->tok].flags & MAN_NOTEXT); if (n == NULL || (n->tok == MAN_SS && n->body->child == NULL)) break; for (i = 0; i < mt->pardist; i++) term_vspace(p); break; - case MAN_HEAD: + case ROFFT_HEAD: term_fontrepl(p, TERMFONT_BOLD); p->offset = term_len(p, 3); + p->rmargin = mt->offset; + p->trailspace = mt->offset; + p->flags |= TERMP_NOBREAK | TERMP_BRIND; break; - case MAN_BODY: + case ROFFT_BODY: p->offset = mt->offset; + p->rmargin = p->maxrmargin; + p->trailspace = 0; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); break; default: break; } - return(1); + return 1; } static void @@ -769,10 +790,10 @@ post_SS(DECL_ARGS) { switch (n->type) { - case MAN_HEAD: + case ROFFT_HEAD: term_newln(p); break; - case MAN_BODY: + case ROFFT_BODY: term_newln(p); break; default: @@ -786,7 +807,7 @@ pre_SH(DECL_ARGS) int i; switch (n->type) { - case MAN_BLOCK: + case ROFFT_BLOCK: mt->fl &= ~MANT_LITERAL; mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); mt->offset = term_len(p, p->defindent); @@ -805,18 +826,24 @@ pre_SH(DECL_ARGS) for (i = 0; i < mt->pardist; i++) term_vspace(p); break; - case MAN_HEAD: + case ROFFT_HEAD: term_fontrepl(p, TERMFONT_BOLD); p->offset = 0; + p->rmargin = mt->offset; + p->trailspace = mt->offset; + p->flags |= TERMP_NOBREAK | TERMP_BRIND; break; - case MAN_BODY: + case ROFFT_BODY: p->offset = mt->offset; + p->rmargin = p->maxrmargin; + p->trailspace = 0; + p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND); break; default: break; } - return(1); + return 1; } static void @@ -824,10 +851,10 @@ post_SH(DECL_ARGS) { switch (n->type) { - case MAN_HEAD: + case ROFFT_HEAD: term_newln(p); break; - case MAN_BODY: + case ROFFT_BODY: term_newln(p); break; default: @@ -841,19 +868,21 @@ pre_RS(DECL_ARGS) struct roffsu su; switch (n->type) { - case MAN_BLOCK: + case ROFFT_BLOCK: term_newln(p); - return(1); - case MAN_HEAD: - return(0); + return 1; + case ROFFT_HEAD: + return 0; default: break; } n = n->parent->head; n->aux = SHRT_MAX + 1; - if (n->child != NULL && a2roffsu(n->child->string, &su, SCALE_EN)) - n->aux = term_hspan(p, &su); + if (n->child == NULL) + n->aux = mt->lmargin[mt->lmargincur]; + else if (a2roffsu(n->child->string, &su, SCALE_EN)) + n->aux = term_hspan(p, &su) / 24; if (n->aux < 0 && (size_t)(-n->aux) > mt->offset) n->aux = -mt->offset; else if (n->aux > SHRT_MAX) @@ -866,8 +895,8 @@ pre_RS(DECL_ARGS) if (++mt->lmarginsz < MAXMARGINS) mt->lmargincur = mt->lmarginsz; - mt->lmargin[mt->lmargincur] = mt->lmargin[mt->lmargincur - 1]; - return(1); + mt->lmargin[mt->lmargincur] = term_len(p, p->defindent); + return 1; } static void @@ -875,9 +904,9 @@ post_RS(DECL_ARGS) { switch (n->type) { - case MAN_BLOCK: + case ROFFT_BLOCK: return; - case MAN_HEAD: + case ROFFT_HEAD: return; default: term_newln(p); @@ -895,14 +924,14 @@ static int pre_UR(DECL_ARGS) { - return (MAN_HEAD != n->type); + return n->type != ROFFT_HEAD; } static void post_UR(DECL_ARGS) { - if (MAN_BLOCK != n->type) + if (n->type != ROFFT_BLOCK) return; term_word(p, "<"); @@ -922,7 +951,7 @@ print_man_node(DECL_ARGS) int c; switch (n->type) { - case MAN_TEXT: + case ROFFT_TEXT: /* * If we have a blank line, output a vertical space. * If we have a space as the first character, break @@ -937,14 +966,14 @@ print_man_node(DECL_ARGS) term_word(p, n->string); goto out; - case MAN_EQN: + case ROFFT_EQN: if ( ! (n->flags & MAN_LINE)) p->flags |= TERMP_NOSPACE; term_eqn(p, n->eqn); if (n->next != NULL && ! (n->next->flags & MAN_LINE)) p->flags |= TERMP_NOSPACE; return; - case MAN_TBL: + case ROFFT_TBL: if (p->tbl.cols == NULL) term_vspace(p); term_tbl(p, n->span); @@ -1010,13 +1039,11 @@ print_man_nodelist(DECL_ARGS) } static void -print_man_foot(struct termp *p, const void *arg) +print_man_foot(struct termp *p, const struct roff_meta *meta) { - const struct man_meta *meta; char *title; size_t datelen, titlen; - meta = (const struct man_meta *)arg; assert(meta->title); assert(meta->msec); assert(meta->date); @@ -1028,8 +1055,8 @@ print_man_foot(struct termp *p, const void *arg) /* * Temporary, undocumented option to imitate mdoc(7) output. - * In the bottom right corner, use the source instead of - * the title. + * In the bottom right corner, use the operating system + * instead of the title. */ if ( ! p->mdocstyle) { @@ -1039,14 +1066,14 @@ print_man_foot(struct termp *p, const void *arg) } mandoc_asprintf(&title, "%s(%s)", meta->title, meta->msec); - } else if (meta->source) { - title = mandoc_strdup(meta->source); + } else if (meta->os) { + title = mandoc_strdup(meta->os); } else { title = mandoc_strdup(""); } datelen = term_strlen(p, meta->date); - /* Bottom left corner: manual source. */ + /* Bottom left corner: operating system. */ p->flags |= TERMP_NOSPACE | TERMP_NOBREAK; p->trailspace = 1; @@ -1054,8 +1081,8 @@ print_man_foot(struct termp *p, const void *arg) p->rmargin = p->maxrmargin > datelen ? (p->maxrmargin + term_len(p, 1) - datelen) / 2 : 0; - if (meta->source) - term_word(p, meta->source); + if (meta->os) + term_word(p, meta->os); term_flushln(p); /* At the bottom in the middle: manual date. */ @@ -1082,14 +1109,12 @@ print_man_foot(struct termp *p, const void *arg) } static void -print_man_head(struct termp *p, const void *arg) +print_man_head(struct termp *p, const struct roff_meta *meta) { - const struct man_meta *meta; const char *volume; char *title; size_t vollen, titlen; - meta = (const struct man_meta *)arg; assert(meta->title); assert(meta->msec); diff --git a/usr/src/cmd/mandoc/man_validate.c b/usr/src/cmd/mandoc/man_validate.c index 93ee9b3f20..16d996355e 100644 --- a/usr/src/cmd/mandoc/man_validate.c +++ b/usr/src/cmd/mandoc/man_validate.c @@ -1,15 +1,15 @@ /* $OpenBSD$ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -28,13 +28,15 @@ #include <string.h> #include <time.h> -#include "man.h" -#include "mandoc.h" #include "mandoc_aux.h" -#include "libman.h" +#include "mandoc.h" +#include "roff.h" +#include "man.h" #include "libmandoc.h" +#include "roff_int.h" +#include "libman.h" -#define CHKARGS struct man *man, struct man_node *n +#define CHKARGS struct roff_man *man, struct roff_node *n typedef void (*v_check)(CHKARGS); @@ -46,9 +48,7 @@ static void check_text(CHKARGS); static void post_AT(CHKARGS); static void post_IP(CHKARGS); static void post_vs(CHKARGS); -static void post_fi(CHKARGS); static void post_ft(CHKARGS); -static void post_nf(CHKARGS); static void post_OP(CHKARGS); static void post_TH(CHKARGS); static void post_UC(CHKARGS); @@ -77,8 +77,8 @@ static v_check man_valids[MAN_MAX] = { NULL, /* IR */ NULL, /* RI */ post_vs, /* sp */ - post_nf, /* nf */ - post_fi, /* fi */ + NULL, /* nf */ + NULL, /* fi */ NULL, /* RE */ check_part, /* RS */ NULL, /* DT */ @@ -88,8 +88,8 @@ static v_check man_valids[MAN_MAX] = { NULL, /* in */ post_ft, /* ft */ post_OP, /* OP */ - post_nf, /* EX */ - post_fi, /* EE */ + NULL, /* EX */ + NULL, /* EE */ post_UR, /* UR */ NULL, /* UE */ NULL, /* ll */ @@ -97,31 +97,39 @@ static v_check man_valids[MAN_MAX] = { void -man_valid_post(struct man *man) +man_node_validate(struct roff_man *man) { - struct man_node *n; + struct roff_node *n; v_check *cp; n = man->last; - if (n->flags & MAN_VALID) - return; - n->flags |= MAN_VALID; + man->last = man->last->child; + while (man->last != NULL) { + man_node_validate(man); + if (man->last == n) + man->last = man->last->child; + else + man->last = man->last->next; + } + man->last = n; + man->next = ROFF_NEXT_SIBLING; switch (n->type) { - case MAN_TEXT: + case ROFFT_TEXT: check_text(man, n); break; - case MAN_ROOT: + case ROFFT_ROOT: check_root(man, n); break; - case MAN_EQN: - /* FALLTHROUGH */ - case MAN_TBL: + case ROFFT_EQN: + case ROFFT_TBL: break; default: cp = man_valids + n->tok; if (*cp) (*cp)(man, n); + if (man->last == n) + man_state(man, n); break; } } @@ -172,10 +180,10 @@ static void post_OP(CHKARGS) { - if (n->nchild == 0) + if (n->child == NULL) mandoc_msg(MANDOCERR_OP_EMPTY, man->parse, n->line, n->pos, "OP"); - else if (n->nchild > 2) { + else if (n->child->next != NULL && n->child->next->next != NULL) { n = n->child->next->next; mandoc_vmsg(MANDOCERR_ARG_EXCESS, man->parse, n->line, n->pos, "OP ... %s", n->string); @@ -186,7 +194,7 @@ static void post_UR(CHKARGS) { - if (n->type == MAN_HEAD && n->child == NULL) + if (n->type == ROFFT_HEAD && n->child == NULL) mandoc_vmsg(MANDOCERR_UR_NOHEAD, man->parse, n->line, n->pos, "UR"); check_part(man, n); @@ -198,24 +206,18 @@ post_ft(CHKARGS) char *cp; int ok; - if (0 == n->nchild) + if (n->child == NULL) return; ok = 0; cp = n->child->string; switch (*cp) { case '1': - /* FALLTHROUGH */ case '2': - /* FALLTHROUGH */ case '3': - /* FALLTHROUGH */ case '4': - /* FALLTHROUGH */ case 'I': - /* FALLTHROUGH */ case 'P': - /* FALLTHROUGH */ case 'R': if ('\0' == cp[1]) ok = 1; @@ -243,7 +245,7 @@ static void check_part(CHKARGS) { - if (n->type == MAN_BODY && n->child == NULL) + if (n->type == ROFFT_BODY && n->child == NULL) mandoc_msg(MANDOCERR_BLK_EMPTY, man->parse, n->line, n->pos, man_macronames[n->tok]); } @@ -253,23 +255,23 @@ check_par(CHKARGS) { switch (n->type) { - case MAN_BLOCK: - if (0 == n->body->nchild) - man_node_delete(man, n); + case ROFFT_BLOCK: + if (n->body->child == NULL) + roff_node_delete(man, n); break; - case MAN_BODY: - if (0 == n->nchild) + case ROFFT_BODY: + if (n->child == NULL) mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos, "%s empty", man_macronames[n->tok]); break; - case MAN_HEAD: - if (n->nchild) + case ROFFT_HEAD: + if (n->child != NULL) mandoc_vmsg(MANDOCERR_ARG_SKIP, man->parse, n->line, n->pos, "%s %s%s", man_macronames[n->tok], n->child->string, - n->nchild > 1 ? " ..." : ""); + n->child->next != NULL ? " ..." : ""); break; default: break; @@ -281,12 +283,12 @@ post_IP(CHKARGS) { switch (n->type) { - case MAN_BLOCK: - if (0 == n->head->nchild && 0 == n->body->nchild) - man_node_delete(man, n); + case ROFFT_BLOCK: + if (n->head->child == NULL && n->body->child == NULL) + roff_node_delete(man, n); break; - case MAN_BODY: - if (0 == n->parent->head->nchild && 0 == n->nchild) + case ROFFT_BODY: + if (n->parent->head->child == NULL && n->child == NULL) mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos, "%s empty", man_macronames[n->tok]); @@ -299,21 +301,21 @@ post_IP(CHKARGS) static void post_TH(CHKARGS) { - struct man_node *nb; + struct roff_node *nb; const char *p; free(man->meta.title); free(man->meta.vol); - free(man->meta.source); + free(man->meta.os); free(man->meta.msec); free(man->meta.date); man->meta.title = man->meta.vol = man->meta.date = - man->meta.msec = man->meta.source = NULL; + man->meta.msec = man->meta.os = NULL; nb = n; - /* ->TITLE<- MSEC DATE SOURCE VOL */ + /* ->TITLE<- MSEC DATE OS VOL */ n = n->child; if (n && n->string) { @@ -335,7 +337,7 @@ post_TH(CHKARGS) nb->line, nb->pos, "TH"); } - /* TITLE ->MSEC<- DATE SOURCE VOL */ + /* TITLE ->MSEC<- DATE OS VOL */ if (n) n = n->next; @@ -347,7 +349,7 @@ post_TH(CHKARGS) nb->line, nb->pos, "TH %s", man->meta.title); } - /* TITLE MSEC ->DATE<- SOURCE VOL */ + /* TITLE MSEC ->DATE<- OS VOL */ if (n) n = n->next; @@ -363,14 +365,14 @@ post_TH(CHKARGS) n ? n->pos : nb->pos, "TH"); } - /* TITLE MSEC DATE ->SOURCE<- VOL */ + /* TITLE MSEC DATE ->OS<- VOL */ if (n && (n = n->next)) - man->meta.source = mandoc_strdup(n->string); + man->meta.os = mandoc_strdup(n->string); else if (man->defos != NULL) - man->meta.source = mandoc_strdup(man->defos); + man->meta.os = mandoc_strdup(man->defos); - /* TITLE MSEC DATE SOURCE ->VOL<- */ + /* TITLE MSEC DATE OS ->VOL<- */ /* If missing, use the default VOL name for MSEC. */ if (n && (n = n->next)) @@ -387,29 +389,7 @@ post_TH(CHKARGS) * Remove the `TH' node after we've processed it for our * meta-data. */ - man_node_delete(man, man->last); -} - -static void -post_nf(CHKARGS) -{ - - if (man->flags & MAN_LITERAL) - mandoc_msg(MANDOCERR_NF_SKIP, man->parse, - n->line, n->pos, "nf"); - - man->flags |= MAN_LITERAL; -} - -static void -post_fi(CHKARGS) -{ - - if ( ! (MAN_LITERAL & man->flags)) - mandoc_msg(MANDOCERR_FI_SKIP, man->parse, - n->line, n->pos, "fi"); - - man->flags &= ~MAN_LITERAL; + roff_node_delete(man, man->last); } static void @@ -427,7 +407,7 @@ post_UC(CHKARGS) n = n->child; - if (NULL == n || MAN_TEXT != n->type) + if (n == NULL || n->type != ROFFT_TEXT) p = bsd_versions[0]; else { s = n->string; @@ -445,8 +425,8 @@ post_UC(CHKARGS) p = bsd_versions[0]; } - free(man->meta.source); - man->meta.source = mandoc_strdup(p); + free(man->meta.os); + man->meta.os = mandoc_strdup(p); } static void @@ -459,12 +439,12 @@ post_AT(CHKARGS) "System V Release 2", }; + struct roff_node *nn; const char *p, *s; - struct man_node *nn; n = n->child; - if (NULL == n || MAN_TEXT != n->type) + if (n == NULL || n->type != ROFFT_TEXT) p = unix_versions[0]; else { s = n->string; @@ -474,7 +454,9 @@ post_AT(CHKARGS) p = unix_versions[1]; else if (0 == strcmp(s, "5")) { nn = n->next; - if (nn && MAN_TEXT == nn->type && nn->string[0]) + if (nn != NULL && + nn->type == ROFFT_TEXT && + nn->string[0] != '\0') p = unix_versions[3]; else p = unix_versions[2]; @@ -482,8 +464,8 @@ post_AT(CHKARGS) p = unix_versions[0]; } - free(man->meta.source); - man->meta.source = mandoc_strdup(p); + free(man->meta.os); + man->meta.os = mandoc_strdup(p); } static void @@ -495,18 +477,17 @@ post_vs(CHKARGS) switch (n->parent->tok) { case MAN_SH: - /* FALLTHROUGH */ case MAN_SS: mandoc_vmsg(MANDOCERR_PAR_SKIP, man->parse, n->line, n->pos, "%s after %s", man_macronames[n->tok], man_macronames[n->parent->tok]); /* FALLTHROUGH */ - case MAN_MAX: + case TOKEN_NONE: /* * Don't warn about this because it occurs in pod2man * and would cause considerable (unfixable) warnage. */ - man_node_delete(man, n); + roff_node_delete(man, n); break; default: break; diff --git a/usr/src/cmd/mandoc/manconf.h b/usr/src/cmd/mandoc/manconf.h new file mode 100644 index 0000000000..782269e7b3 --- /dev/null +++ b/usr/src/cmd/mandoc/manconf.h @@ -0,0 +1,48 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* List of unique, absolute paths to manual trees. */ + +struct manpaths { + char **paths; + size_t sz; +}; + +/* Data from -O options and man.conf(5) output directives. */ + +struct manoutput { + char *includes; + char *man; + char *paper; + char *style; + size_t indent; + size_t width; + int fragment; + int mdoc; + int synopsisonly; +}; + +struct manconf { + struct manoutput output; + struct manpaths manpath; +}; + + +void manconf_parse(struct manconf *, const char *, char *, char *); +void manconf_output(struct manoutput *, const char *); +void manconf_free(struct manconf *); diff --git a/usr/src/cmd/mandoc/mandoc.c b/usr/src/cmd/mandoc/mandoc.c index 0619420cb1..d265463b4e 100644 --- a/usr/src/cmd/mandoc/mandoc.c +++ b/usr/src/cmd/mandoc/mandoc.c @@ -1,4 +1,4 @@ -/* $Id: mandoc.c,v 1.92 2015/02/20 23:55:10 schwarze Exp $ */ +/* $Id: mandoc.c,v 1.98 2015/11/12 22:44:27 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -32,8 +32,6 @@ #include "mandoc_aux.h" #include "libmandoc.h" -#define DATESIZE 32 - static int a2time(time_t *, const char *, const char *); static char *time2a(time_t); @@ -83,7 +81,7 @@ mandoc_escape(const char **end, const char **start, int *sz) break; case 'C': if ('\'' != **start) - return(ESCAPE_ERROR); + return ESCAPE_ERROR; *start = ++*end; gly = ESCAPE_SPECIAL; term = '\''; @@ -93,9 +91,10 @@ mandoc_escape(const char **end, const char **start, int *sz) * Escapes taking no arguments at all. */ case 'd': - /* FALLTHROUGH */ case 'u': - return(ESCAPE_IGNORE); + case ',': + case '/': + return ESCAPE_IGNORE; /* * The \z escape is supposed to output the following @@ -104,26 +103,19 @@ mandoc_escape(const char **end, const char **start, int *sz) * let us just skip the next character. */ case 'z': - return(ESCAPE_SKIPCHAR); + return ESCAPE_SKIPCHAR; /* * Handle all triggers matching \X(xy, \Xx, and \X[xxxx], where * 'X' is the trigger. These have opaque sub-strings. */ case 'F': - /* FALLTHROUGH */ case 'g': - /* FALLTHROUGH */ case 'k': - /* FALLTHROUGH */ case 'M': - /* FALLTHROUGH */ case 'm': - /* FALLTHROUGH */ case 'n': - /* FALLTHROUGH */ case 'V': - /* FALLTHROUGH */ case 'Y': gly = ESCAPE_IGNORE; /* FALLTHROUGH */ @@ -151,21 +143,16 @@ mandoc_escape(const char **end, const char **start, int *sz) * The \B and \w escapes are handled in roff.c, roff_res(). */ case 'A': - /* FALLTHROUGH */ case 'b': - /* FALLTHROUGH */ case 'D': - /* FALLTHROUGH */ case 'R': - /* FALLTHROUGH */ case 'X': - /* FALLTHROUGH */ case 'Z': gly = ESCAPE_IGNORE; /* FALLTHROUGH */ case 'o': if (**start == '\0') - return(ESCAPE_ERROR); + return ESCAPE_ERROR; if (gly == ESCAPE_ERROR) gly = ESCAPE_OVERSTRIKE; term = **start; @@ -177,22 +164,16 @@ mandoc_escape(const char **end, const char **start, int *sz) * and 'N' resolves to a numerical expression. */ case 'h': - /* FALLTHROUGH */ case 'H': - /* FALLTHROUGH */ case 'L': - /* FALLTHROUGH */ case 'l': - /* FALLTHROUGH */ case 'S': - /* FALLTHROUGH */ case 'v': - /* FALLTHROUGH */ case 'x': if (strchr(" %&()*+-./0123456789:<=>", **start)) { if ('\0' != **start) ++*end; - return(ESCAPE_ERROR); + return ESCAPE_ERROR; } gly = ESCAPE_IGNORE; term = **start; @@ -205,11 +186,11 @@ mandoc_escape(const char **end, const char **start, int *sz) */ case 'N': if ('\0' == **start) - return(ESCAPE_ERROR); + return ESCAPE_ERROR; (*end)++; if (isdigit((unsigned char)**start)) { *sz = 1; - return(ESCAPE_IGNORE); + return ESCAPE_IGNORE; } (*start)++; while (isdigit((unsigned char)**end)) @@ -217,7 +198,7 @@ mandoc_escape(const char **end, const char **start, int *sz) *sz = *end - *start; if ('\0' != **end) (*end)++; - return(ESCAPE_NUMBERED); + return ESCAPE_NUMBERED; /* * Sizes get a special category of their own. @@ -243,9 +224,7 @@ mandoc_escape(const char **end, const char **start, int *sz) term = '\''; break; case '3': - /* FALLTHROUGH */ case '2': - /* FALLTHROUGH */ case '1': *sz = (*end)[-1] == 's' && isdigit((unsigned char)(*end)[1]) ? 2 : 1; @@ -279,12 +258,12 @@ mandoc_escape(const char **end, const char **start, int *sz) while (**end != term) { switch (**end) { case '\0': - return(ESCAPE_ERROR); + return ESCAPE_ERROR; case '\\': (*end)++; if (ESCAPE_ERROR == mandoc_escape(end, NULL, NULL)) - return(ESCAPE_ERROR); + return ESCAPE_ERROR; break; default: (*end)++; @@ -295,7 +274,7 @@ mandoc_escape(const char **end, const char **start, int *sz) } else { assert(*sz > 0); if ((size_t)*sz > strlen(*start)) - return(ESCAPE_ERROR); + return ESCAPE_ERROR; *end += *sz; } @@ -321,12 +300,10 @@ mandoc_escape(const char **end, const char **start, int *sz) switch (**start) { case '3': - /* FALLTHROUGH */ case 'B': gly = ESCAPE_FONTBOLD; break; case '2': - /* FALLTHROUGH */ case 'I': gly = ESCAPE_FONTITALIC; break; @@ -334,7 +311,6 @@ mandoc_escape(const char **end, const char **start, int *sz) gly = ESCAPE_FONTPREV; break; case '1': - /* FALLTHROUGH */ case 'R': gly = ESCAPE_FONTROMAN; break; @@ -355,6 +331,9 @@ mandoc_escape(const char **end, const char **start, int *sz) break; if (*sz == 6 && (*start)[1] == '0') break; + if (*sz == 5 && (*start)[1] == 'D' && + strchr("89ABCDEF", (*start)[2]) != NULL) + break; if ((int)strspn(*start + 1, "0123456789ABCDEFabcdef") + 1 == *sz) gly = ESCAPE_UNICODE; @@ -363,7 +342,7 @@ mandoc_escape(const char **end, const char **start, int *sz) break; } - return(gly); + return gly; } /* @@ -458,7 +437,7 @@ mandoc_getarg(struct mparse *parse, char **cpp, int ln, int *pos) if ('\0' == *cp && (white || ' ' == cp[-1])) mandoc_msg(MANDOCERR_SPACE_EOL, parse, ln, *pos, NULL); - return(start); + return start; } static int @@ -475,10 +454,10 @@ a2time(time_t *t, const char *fmt, const char *p) #endif if (NULL != pp && '\0' == *pp) { *t = mktime(&tm); - return(1); + return 1; } - return(0); + return 0; } static char * @@ -491,7 +470,7 @@ time2a(time_t t) tm = localtime(&t); if (tm == NULL) - return(NULL); + return NULL; /* * Reserve space: @@ -499,45 +478,61 @@ time2a(time_t t) * up to 2 characters for the day + comma + blank * 4 characters for the year and a terminating '\0' */ + p = buf = mandoc_malloc(10 + 4 + 4 + 1); - if (0 == (ssz = strftime(p, 10 + 1, "%B ", tm))) + if ((ssz = strftime(p, 10 + 1, "%B ", tm)) == 0) goto fail; p += (int)ssz; - if (-1 == (isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday))) + /* + * The output format is just "%d" here, not "%2d" or "%02d". + * That's also the reason why we can't just format the + * date as a whole with "%B %e, %Y" or "%B %d, %Y". + * Besides, the present approach is less prone to buffer + * overflows, in case anybody should ever introduce the bug + * of looking at LC_TIME. + */ + + if ((isz = snprintf(p, 4 + 1, "%d, ", tm->tm_mday)) == -1) goto fail; p += isz; - if (0 == strftime(p, 4 + 1, "%Y", tm)) + if (strftime(p, 4 + 1, "%Y", tm) == 0) goto fail; - return(buf); + return buf; fail: free(buf); - return(NULL); + return NULL; } char * mandoc_normdate(struct mparse *parse, char *in, int ln, int pos) { - char *out; time_t t; - if (NULL == in || '\0' == *in || - 0 == strcmp(in, "$" "Mdocdate$")) { + /* No date specified: use today's date. */ + + if (in == NULL || *in == '\0' || strcmp(in, "$" "Mdocdate$") == 0) { mandoc_msg(MANDOCERR_DATE_MISSING, parse, ln, pos, NULL); - time(&t); + return time2a(time(NULL)); } - else if (a2time(&t, "%Y-%m-%d", in)) - t = 0; - else if (!a2time(&t, "$" "Mdocdate: %b %d %Y $", in) && - !a2time(&t, "%b %d, %Y", in)) { + + /* Valid mdoc(7) date format. */ + + if (a2time(&t, "$" "Mdocdate: %b %d %Y $", in) || + a2time(&t, "%b %d, %Y", in)) + return time2a(t); + + /* Do not warn about the legacy man(7) format. */ + + if ( ! a2time(&t, "%Y-%m-%d", in)) mandoc_msg(MANDOCERR_DATE_BAD, parse, ln, pos, in); - t = 0; - } - out = t ? time2a(t) : NULL; - return(out ? out : mandoc_strdup(in)); + + /* Use any non-mdoc(7) date verbatim. */ + + return mandoc_strdup(in); } int @@ -547,7 +542,7 @@ mandoc_eos(const char *p, size_t sz) int enclosed, found; if (0 == sz) - return(0); + return 0; /* * End-of-sentence recognition must include situations where @@ -559,28 +554,24 @@ mandoc_eos(const char *p, size_t sz) for (q = p + (int)sz - 1; q >= p; q--) { switch (*q) { case '\"': - /* FALLTHROUGH */ case '\'': - /* FALLTHROUGH */ case ']': - /* FALLTHROUGH */ case ')': if (0 == found) enclosed = 1; break; case '.': - /* FALLTHROUGH */ case '!': - /* FALLTHROUGH */ case '?': found = 1; break; default: - return(found && (!enclosed || isalnum((unsigned char)*q))); + return found && + (!enclosed || isalnum((unsigned char)*q)); } } - return(found && !enclosed); + return found && !enclosed; } /* @@ -595,7 +586,7 @@ mandoc_strntoi(const char *p, size_t sz, int base) long v; if (sz > 31) - return(-1); + return -1; memcpy(buf, p, sz); buf[(int)sz] = '\0'; @@ -604,12 +595,12 @@ mandoc_strntoi(const char *p, size_t sz, int base) v = strtol(buf, &ep, base); if (buf[0] == '\0' || *ep != '\0') - return(-1); + return -1; if (v > INT_MAX) v = INT_MAX; if (v < INT_MIN) v = INT_MIN; - return((int)v); + return (int)v; } diff --git a/usr/src/cmd/mandoc/mandoc.h b/usr/src/cmd/mandoc/mandoc.h index eb8a1aa6f2..d63814c6de 100644 --- a/usr/src/cmd/mandoc/mandoc.h +++ b/usr/src/cmd/mandoc/mandoc.h @@ -1,15 +1,15 @@ -/* $Id: mandoc.h,v 1.201 2015/02/23 13:31:04 schwarze Exp $ */ +/* $Id: mandoc.h,v 1.209 2016/01/08 02:53:13 schwarze Exp $ */ /* * Copyright (c) 2010, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -86,7 +86,6 @@ enum mandocerr { MANDOCERR_BLK_NEST, /* blocks badly nested: macro ... */ MANDOCERR_BD_NEST, /* nested displays are not portable: macro ... */ MANDOCERR_BL_MOVE, /* moving content out of list: macro */ - MANDOCERR_VT_CHILD, /* .Vt block has child macro: macro */ MANDOCERR_FI_SKIP, /* fill mode already enabled, skipping: fi */ MANDOCERR_NF_SKIP, /* fill mode already disabled, skipping: nf */ MANDOCERR_BLK_LINE, /* line scope broken: macro breaks macro */ @@ -173,6 +172,7 @@ enum mandocerr { /* related to request and macro arguments */ MANDOCERR_NAMESC, /* escaped character not allowed in a name: name */ MANDOCERR_BD_FILE, /* NOT IMPLEMENTED: Bd -file */ + MANDOCERR_BD_NOARG, /* skipping display without arguments: Bd */ MANDOCERR_BL_NOTYPE, /* missing list type, using -item: Bl */ MANDOCERR_NM_NONAME, /* missing manual name, using "": Nm */ MANDOCERR_OS_UNAME, /* uname(3) system call failed, using UNKNOWN */ @@ -408,37 +408,28 @@ enum mandoc_esc { typedef void (*mandocmsg)(enum mandocerr, enum mandoclevel, const char *, int, int, const char *); -__BEGIN_DECLS struct mparse; -struct mchars; -struct mdoc; -struct man; +struct roff_man; enum mandoc_esc mandoc_escape(const char **, const char **, int *); -struct mchars *mchars_alloc(void); -void mchars_free(struct mchars *); +void mchars_alloc(void); +void mchars_free(void); int mchars_num2char(const char *, size_t); const char *mchars_uc2str(int); int mchars_num2uc(const char *, size_t); -int mchars_spec2cp(const struct mchars *, - const char *, size_t); -const char *mchars_spec2str(const struct mchars *, - const char *, size_t, size_t *); -struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg, - const struct mchars *, const char *); +int mchars_spec2cp(const char *, size_t); +const char *mchars_spec2str(const char *, size_t, size_t *); +struct mparse *mparse_alloc(int, enum mandoclevel, mandocmsg, const char *); void mparse_free(struct mparse *); void mparse_keep(struct mparse *); -enum mandoclevel mparse_open(struct mparse *, int *, const char *); +int mparse_open(struct mparse *, const char *); enum mandoclevel mparse_readfd(struct mparse *, int, const char *); enum mandoclevel mparse_readmem(struct mparse *, void *, size_t, const char *); void mparse_reset(struct mparse *); void mparse_result(struct mparse *, - struct mdoc **, struct man **, char **); + struct roff_man **, char **); const char *mparse_getkeep(const struct mparse *); const char *mparse_strerror(enum mandocerr); const char *mparse_strlevel(enum mandoclevel); -enum mandoclevel mparse_wait(struct mparse *); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/mandoc_aux.c b/usr/src/cmd/mandoc/mandoc_aux.c index 2275bbcf36..cc74b7e720 100644 --- a/usr/src/cmd/mandoc/mandoc_aux.c +++ b/usr/src/cmd/mandoc/mandoc_aux.c @@ -1,4 +1,4 @@ -/* $Id: mandoc_aux.c,v 1.4 2014/08/10 23:54:41 schwarze Exp $ */ +/* $Id: mandoc_aux.c,v 1.9 2015/11/07 14:22:29 schwarze Exp $ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -19,6 +19,9 @@ #include <sys/types.h> +#if HAVE_ERR +#include <err.h> +#endif #include <stdarg.h> #include <stdlib.h> #include <stdio.h> @@ -27,6 +30,7 @@ #include "mandoc.h" #include "mandoc_aux.h" + int mandoc_asprintf(char **dest, const char *fmt, ...) { @@ -37,11 +41,9 @@ mandoc_asprintf(char **dest, const char *fmt, ...) ret = vasprintf(dest, fmt, ap); va_end(ap); - if (-1 == ret) { - perror(NULL); - exit((int)MANDOCLEVEL_SYSERR); - } - return(ret); + if (ret == -1) + err((int)MANDOCLEVEL_SYSERR, NULL); + return ret; } void * @@ -50,11 +52,9 @@ mandoc_calloc(size_t num, size_t size) void *ptr; ptr = calloc(num, size); - if (NULL == ptr) { - perror(NULL); - exit((int)MANDOCLEVEL_SYSERR); - } - return(ptr); + if (ptr == NULL) + err((int)MANDOCLEVEL_SYSERR, NULL); + return ptr; } void * @@ -63,11 +63,9 @@ mandoc_malloc(size_t size) void *ptr; ptr = malloc(size); - if (NULL == ptr) { - perror(NULL); - exit((int)MANDOCLEVEL_SYSERR); - } - return(ptr); + if (ptr == NULL) + err((int)MANDOCLEVEL_SYSERR, NULL); + return ptr; } void * @@ -75,11 +73,9 @@ mandoc_realloc(void *ptr, size_t size) { ptr = realloc(ptr, size); - if (NULL == ptr) { - perror(NULL); - exit((int)MANDOCLEVEL_SYSERR); - } - return(ptr); + if (ptr == NULL) + err((int)MANDOCLEVEL_SYSERR, NULL); + return ptr; } void * @@ -87,11 +83,9 @@ mandoc_reallocarray(void *ptr, size_t num, size_t size) { ptr = reallocarray(ptr, num, size); - if (NULL == ptr) { - perror(NULL); - exit((int)MANDOCLEVEL_SYSERR); - } - return(ptr); + if (ptr == NULL) + err((int)MANDOCLEVEL_SYSERR, NULL); + return ptr; } char * @@ -100,11 +94,9 @@ mandoc_strdup(const char *ptr) char *p; p = strdup(ptr); - if (NULL == p) { - perror(NULL); - exit((int)MANDOCLEVEL_SYSERR); - } - return(p); + if (p == NULL) + err((int)MANDOCLEVEL_SYSERR, NULL); + return p; } char * @@ -115,5 +107,5 @@ mandoc_strndup(const char *ptr, size_t sz) p = mandoc_malloc(sz + 1); memcpy(p, ptr, sz); p[(int)sz] = '\0'; - return(p); + return p; } diff --git a/usr/src/cmd/mandoc/mandoc_aux.h b/usr/src/cmd/mandoc/mandoc_aux.h index e72fe4e40e..2ae3a0cd2d 100644 --- a/usr/src/cmd/mandoc/mandoc_aux.h +++ b/usr/src/cmd/mandoc/mandoc_aux.h @@ -1,4 +1,4 @@ -/* $Id: mandoc_aux.h,v 1.3 2014/12/01 04:05:32 schwarze Exp $ */ +/* $Id: mandoc_aux.h,v 1.4 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -16,8 +16,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -__BEGIN_DECLS - int mandoc_asprintf(char **, const char *, ...); void *mandoc_calloc(size_t, size_t); void *mandoc_malloc(size_t); @@ -25,5 +23,3 @@ void *mandoc_realloc(void *, size_t); void *mandoc_reallocarray(void *, size_t, size_t); char *mandoc_strdup(const char *); char *mandoc_strndup(const char *, size_t); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/mandoc_ohash.c b/usr/src/cmd/mandoc/mandoc_ohash.c new file mode 100644 index 0000000000..0627b469c6 --- /dev/null +++ b/usr/src/cmd/mandoc/mandoc_ohash.c @@ -0,0 +1,63 @@ +/* $Id: mandoc_ohash.c,v 1.2 2015/10/19 18:58:47 schwarze Exp $ */ +/* + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <sys/types.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> + +#include "mandoc_aux.h" +#include "mandoc_ohash.h" + +static void *hash_alloc(size_t, void *); +static void *hash_calloc(size_t, size_t, void *); +static void hash_free(void *, void *); + + +void +mandoc_ohash_init(struct ohash *h, unsigned int sz, ptrdiff_t ko) +{ + struct ohash_info info; + + info.alloc = hash_alloc; + info.calloc = hash_calloc; + info.free = hash_free; + info.data = NULL; + info.key_offset = ko; + + ohash_init(h, sz, &info); +} + +static void * +hash_alloc(size_t sz, void *arg) +{ + + return mandoc_malloc(sz); +} + +static void * +hash_calloc(size_t n, size_t sz, void *arg) +{ + + return mandoc_calloc(n, sz); +} + +static void +hash_free(void *p, void *arg) +{ + + free(p); +} diff --git a/usr/src/cmd/mandoc/mandoc_ohash.h b/usr/src/cmd/mandoc/mandoc_ohash.h new file mode 100644 index 0000000000..571c4cda93 --- /dev/null +++ b/usr/src/cmd/mandoc/mandoc_ohash.h @@ -0,0 +1,23 @@ +/* $Id: mandoc_ohash.h,v 1.2 2015/11/07 14:01:16 schwarze Exp $ */ +/* + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#if HAVE_OHASH +#include <ohash.h> +#else +#include "compat_ohash.h" +#endif + +void mandoc_ohash_init(struct ohash *, unsigned int, ptrdiff_t); diff --git a/usr/src/cmd/mandoc/manpath.c b/usr/src/cmd/mandoc/manpath.c index e85175e945..83c329ec9b 100644 --- a/usr/src/cmd/mandoc/manpath.c +++ b/usr/src/cmd/mandoc/manpath.c @@ -1,15 +1,15 @@ -/* $Id: manpath.c,v 1.19 2014/11/27 00:30:40 schwarze Exp $ */ +/* $Id: manpath.c,v 1.30 2016/05/28 13:44:13 schwarze Exp $ */ /* - * Copyright (c) 2011, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -20,24 +20,27 @@ #include <sys/types.h> #include <sys/stat.h> -#include <assert.h> #include <ctype.h> +#if HAVE_ERR +#include <err.h> +#endif #include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "mandoc_aux.h" -#include "manpath.h" - -#define MAN_CONF_FILE "/etc/man.conf" -#define MAN_CONF_KEY "_whatdb" +#include "manconf.h" +#if !HAVE_MANPATH +static void manconf_file(struct manconf *, const char *); +#endif static void manpath_add(struct manpaths *, const char *, int); static void manpath_parseline(struct manpaths *, char *, int); + void -manpath_parse(struct manpaths *dirs, const char *file, +manconf_parse(struct manconf *conf, const char *file, char *defp, char *auxp) { #if HAVE_MANPATH @@ -80,7 +83,7 @@ manpath_parse(struct manpaths *dirs, const char *file, if ( ! ferror(stream) && feof(stream) && bsz && '\n' == buf[bsz - 1]) { buf[bsz - 1] = '\0'; - manpath_parseline(dirs, buf, 1); + manpath_parseline(&conf->manpath, buf, 1); } free(buf); @@ -89,11 +92,11 @@ manpath_parse(struct manpaths *dirs, const char *file, char *insert; /* Always prepend -m. */ - manpath_parseline(dirs, auxp, 1); + manpath_parseline(&conf->manpath, auxp, 1); /* If -M is given, it overrides everything else. */ if (NULL != defp) { - manpath_parseline(dirs, defp, 1); + manpath_parseline(&conf->manpath, defp, 1); return; } @@ -104,21 +107,21 @@ manpath_parse(struct manpaths *dirs, const char *file, /* No MANPATH; use man.conf(5) only. */ if (NULL == defp || '\0' == defp[0]) { - manpath_manconf(dirs, file); + manconf_file(conf, file); return; } /* Prepend man.conf(5) to MANPATH. */ if (':' == defp[0]) { - manpath_manconf(dirs, file); - manpath_parseline(dirs, defp, 0); + manconf_file(conf, file); + manpath_parseline(&conf->manpath, defp, 0); return; } /* Append man.conf(5) to MANPATH. */ if (':' == defp[strlen(defp) - 1]) { - manpath_parseline(dirs, defp, 0); - manpath_manconf(dirs, file); + manpath_parseline(&conf->manpath, defp, 0); + manconf_file(conf, file); return; } @@ -126,14 +129,14 @@ manpath_parse(struct manpaths *dirs, const char *file, insert = strstr(defp, "::"); if (NULL != insert) { *insert++ = '\0'; - manpath_parseline(dirs, defp, 0); - manpath_manconf(dirs, file); - manpath_parseline(dirs, insert + 1, 0); + manpath_parseline(&conf->manpath, defp, 0); + manconf_file(conf, file); + manpath_parseline(&conf->manpath, insert + 1, 0); return; } /* MANPATH overrides man.conf(5) completely. */ - manpath_parseline(dirs, defp, 0); + manpath_parseline(&conf->manpath, defp, 0); #endif } @@ -165,10 +168,8 @@ manpath_add(struct manpaths *dirs, const char *dir, int complain) size_t i; if (NULL == (cp = realpath(dir, buf))) { - if (complain) { - fputs("manpath: ", stderr); - perror(dir); - } + if (complain) + warn("manpath: %s", dir); return; } @@ -177,10 +178,8 @@ manpath_add(struct manpaths *dirs, const char *dir, int complain) return; if (stat(cp, &sb) == -1) { - if (complain) { - fputs("manpath: ", stderr); - perror(dir); - } + if (complain) + warn("manpath: %s", dir); return; } @@ -191,47 +190,146 @@ manpath_add(struct manpaths *dirs, const char *dir, int complain) } void -manpath_free(struct manpaths *p) +manconf_free(struct manconf *conf) { size_t i; - for (i = 0; i < p->sz; i++) - free(p->paths[i]); + for (i = 0; i < conf->manpath.sz; i++) + free(conf->manpath.paths[i]); - free(p->paths); + free(conf->manpath.paths); + free(conf->output.includes); + free(conf->output.man); + free(conf->output.paper); + free(conf->output.style); } -void -manpath_manconf(struct manpaths *dirs, const char *file) +#if !HAVE_MANPATH +static void +manconf_file(struct manconf *conf, const char *file) { + const char *const toks[] = { "manpath", "output", "_whatdb" }; + char manpath_default[] = MANPATH_DEFAULT; + FILE *stream; - char *p, *q; - size_t len, keysz; + char *line, *cp, *ep; + size_t linesz, tok, toklen; + ssize_t linelen; + + if ((stream = fopen(file, "r")) == NULL) + goto out; + + line = NULL; + linesz = 0; + + while ((linelen = getline(&line, &linesz, stream)) != -1) { + cp = line; + ep = cp + linelen - 1; + while (ep > cp && isspace((unsigned char)*ep)) + *ep-- = '\0'; + while (isspace((unsigned char)*cp)) + cp++; + if (cp == ep || *cp == '#') + continue; - keysz = strlen(MAN_CONF_KEY); - assert(keysz > 0); + for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) { + toklen = strlen(toks[tok]); + if (cp + toklen < ep && + isspace((unsigned char)cp[toklen]) && + strncmp(cp, toks[tok], toklen) == 0) { + cp += toklen; + while (isspace((unsigned char)*cp)) + cp++; + break; + } + } - if (NULL == (stream = fopen(file, "r"))) - return; + switch (tok) { + case 2: /* _whatdb */ + while (ep > cp && ep[-1] != '/') + ep--; + if (ep == cp) + continue; + *ep = '\0'; + /* FALLTHROUGH */ + case 0: /* manpath */ + manpath_add(&conf->manpath, cp, 0); + *manpath_default = '\0'; + break; + case 1: /* output */ + manconf_output(&conf->output, cp); + break; + default: + break; + } + } + free(line); + fclose(stream); + +out: + if (*manpath_default != '\0') + manpath_parseline(&conf->manpath, manpath_default, 0); +} +#endif - while (NULL != (p = fgetln(stream, &len))) { - if (0 == len || '\n' != p[--len]) +void +manconf_output(struct manoutput *conf, const char *cp) +{ + const char *const toks[] = { + "includes", "man", "paper", "style", + "indent", "width", "fragment", "mdoc" + }; + + size_t len, tok; + + for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) { + len = strlen(toks[tok]); + if ( ! strncmp(cp, toks[tok], len) && + strchr(" = ", cp[len]) != NULL) { + cp += len; + if (*cp == '=') + cp++; + while (isspace((unsigned char)*cp)) + cp++; break; - p[len] = '\0'; - while (isspace((unsigned char)*p)) - p++; - if (strncmp(MAN_CONF_KEY, p, keysz)) - continue; - p += keysz; - while (isspace((unsigned char)*p)) - p++; - if ('\0' == *p) - continue; - if (NULL == (q = strrchr(p, '/'))) - continue; - *q = '\0'; - manpath_add(dirs, p, 0); + } } - fclose(stream); + if (tok < 6 && *cp == '\0') + return; + + switch (tok) { + case 0: + if (conf->includes == NULL) + conf->includes = mandoc_strdup(cp); + break; + case 1: + if (conf->man == NULL) + conf->man = mandoc_strdup(cp); + break; + case 2: + if (conf->paper == NULL) + conf->paper = mandoc_strdup(cp); + break; + case 3: + if (conf->style == NULL) + conf->style = mandoc_strdup(cp); + break; + case 4: + if (conf->indent == 0) + conf->indent = strtonum(cp, 0, 1000, NULL); + break; + case 5: + if (conf->width == 0) + conf->width = strtonum(cp, 58, 1000, NULL); + break; + case 6: + conf->fragment = 1; + break; + case 7: + conf->mdoc = 1; + break; + default: + break; + } } diff --git a/usr/src/cmd/mandoc/mansearch.h b/usr/src/cmd/mandoc/mansearch.h index 14ec8ceacd..7f68ff6767 100644 --- a/usr/src/cmd/mandoc/mansearch.h +++ b/usr/src/cmd/mandoc/mansearch.h @@ -1,4 +1,4 @@ -/* $Id: mansearch.h,v 1.23 2014/12/01 08:05:52 schwarze Exp $ */ +/* $Id: mansearch.h,v 1.24 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -95,7 +95,6 @@ struct mansearch { int firstmatch; /* first matching database only */ }; -__BEGIN_DECLS struct manpaths; @@ -107,5 +106,3 @@ int mansearch(const struct mansearch *cfg, /* options */ struct manpage **res, /* results */ size_t *ressz); /* results returned */ void mansearch_free(struct manpage *, size_t); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/mdoc.c b/usr/src/cmd/mandoc/mdoc.c index 027ecbeb31..724d45c652 100644 --- a/usr/src/cmd/mandoc/mdoc.c +++ b/usr/src/cmd/mandoc/mdoc.c @@ -1,4 +1,4 @@ -/* $Id: mdoc.c,v 1.238 2015/02/12 13:00:52 schwarze Exp $ */ +/* $Id: mdoc.c,v 1.256 2015/10/30 19:04:16 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -27,13 +27,16 @@ #include <string.h> #include <time.h> -#include "mdoc.h" -#include "mandoc.h" #include "mandoc_aux.h" -#include "libmdoc.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" +#include "libmdoc.h" const char *const __mdoc_macronames[MDOC_MAX + 1] = { + "text", "Ap", "Dd", "Dt", "Os", "Sh", "Ss", "Pp", "D1", "Dl", "Bd", "Ed", "Bl", @@ -64,8 +67,8 @@ const char *const __mdoc_macronames[MDOC_MAX + 1] = { "Lk", "Mt", "Brq", "Bro", "Brc", "%C", "Es", "En", "Dx", "%Q", "br", "sp", - "%U", "Ta", "ll", "text", - }; + "%U", "Ta", "ll", +}; const char *const __mdoc_argnames[MDOC_ARG_MAX] = { "split", "nosplit", "ragged", @@ -79,157 +82,22 @@ const char *const __mdoc_argnames[MDOC_ARG_MAX] = { "symbolic", "nested", "centered" }; -const char * const *mdoc_macronames = __mdoc_macronames; +const char * const *mdoc_macronames = __mdoc_macronames + 1; const char * const *mdoc_argnames = __mdoc_argnames; -static void mdoc_node_free(struct mdoc_node *); -static void mdoc_node_unlink(struct mdoc *, - struct mdoc_node *); -static void mdoc_free1(struct mdoc *); -static void mdoc_alloc1(struct mdoc *); -static struct mdoc_node *node_alloc(struct mdoc *, int, int, - enum mdoct, enum mdoc_type); -static void node_append(struct mdoc *, struct mdoc_node *); -static int mdoc_ptext(struct mdoc *, int, char *, int); -static int mdoc_pmacro(struct mdoc *, int, char *, int); - - -const struct mdoc_node * -mdoc_node(const struct mdoc *mdoc) -{ - - return(mdoc->first); -} - -const struct mdoc_meta * -mdoc_meta(const struct mdoc *mdoc) -{ - - return(&mdoc->meta); -} - -/* - * Frees volatile resources (parse tree, meta-data, fields). - */ -static void -mdoc_free1(struct mdoc *mdoc) -{ - - if (mdoc->first) - mdoc_node_delete(mdoc, mdoc->first); - free(mdoc->meta.msec); - free(mdoc->meta.vol); - free(mdoc->meta.arch); - free(mdoc->meta.date); - free(mdoc->meta.title); - free(mdoc->meta.os); - free(mdoc->meta.name); -} - -/* - * Allocate all volatile resources (parse tree, meta-data, fields). - */ -static void -mdoc_alloc1(struct mdoc *mdoc) -{ - - memset(&mdoc->meta, 0, sizeof(struct mdoc_meta)); - mdoc->flags = 0; - mdoc->lastnamed = mdoc->lastsec = SEC_NONE; - mdoc->last = mandoc_calloc(1, sizeof(struct mdoc_node)); - mdoc->first = mdoc->last; - mdoc->last->type = MDOC_ROOT; - mdoc->last->tok = MDOC_MAX; - mdoc->next = MDOC_NEXT_CHILD; -} - -/* - * Free up volatile resources (see mdoc_free1()) then re-initialises the - * data with mdoc_alloc1(). After invocation, parse data has been reset - * and the parser is ready for re-invocation on a new tree; however, - * cross-parse non-volatile data is kept intact. - */ -void -mdoc_reset(struct mdoc *mdoc) -{ - - mdoc_free1(mdoc); - mdoc_alloc1(mdoc); -} - -/* - * Completely free up all volatile and non-volatile parse resources. - * After invocation, the pointer is no longer usable. - */ -void -mdoc_free(struct mdoc *mdoc) -{ - - mdoc_free1(mdoc); - free(mdoc); -} - -/* - * Allocate volatile and non-volatile parse resources. - */ -struct mdoc * -mdoc_alloc(struct roff *roff, struct mparse *parse, - const char *defos, int quick) -{ - struct mdoc *p; - - p = mandoc_calloc(1, sizeof(struct mdoc)); - - p->parse = parse; - p->defos = defos; - p->quick = quick; - p->roff = roff; - - mdoc_hash_init(); - mdoc_alloc1(p); - return(p); -} - -void -mdoc_endparse(struct mdoc *mdoc) -{ - - mdoc_macroend(mdoc); -} - -void -mdoc_addeqn(struct mdoc *mdoc, const struct eqn *ep) -{ - struct mdoc_node *n; - - n = node_alloc(mdoc, ep->ln, ep->pos, MDOC_MAX, MDOC_EQN); - n->eqn = ep; - if (ep->ln > mdoc->last->line) - n->flags |= MDOC_LINE; - node_append(mdoc, n); - mdoc->next = MDOC_NEXT_SIBLING; -} +static int mdoc_ptext(struct roff_man *, int, char *, int); +static int mdoc_pmacro(struct roff_man *, int, char *, int); -void -mdoc_addspan(struct mdoc *mdoc, const struct tbl_span *sp) -{ - struct mdoc_node *n; - - n = node_alloc(mdoc, sp->line, 0, MDOC_MAX, MDOC_TBL); - n->span = sp; - node_append(mdoc, n); - mdoc->next = MDOC_NEXT_SIBLING; -} /* * Main parse routine. Parses a single line -- really just hands off to * the macro (mdoc_pmacro()) or text parser (mdoc_ptext()). */ int -mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs) +mdoc_parseln(struct roff_man *mdoc, int ln, char *buf, int offs) { - if (mdoc->last->type != MDOC_EQN || ln > mdoc->last->line) + if (mdoc->last->type != ROFFT_EQN || ln > mdoc->last->line) mdoc->flags |= MDOC_NEWLINE; /* @@ -243,231 +111,80 @@ mdoc_parseln(struct mdoc *mdoc, int ln, char *buf, int offs) else mdoc->flags &= ~MDOC_SYNOPSIS; - return(roff_getcontrol(mdoc->roff, buf, &offs) ? + return roff_getcontrol(mdoc->roff, buf, &offs) ? mdoc_pmacro(mdoc, ln, buf, offs) : - mdoc_ptext(mdoc, ln, buf, offs)); + mdoc_ptext(mdoc, ln, buf, offs); } void mdoc_macro(MACRO_PROT_ARGS) { - assert(tok < MDOC_MAX); - - if (mdoc->flags & MDOC_PBODY) { - if (tok == MDOC_Dt) { - mandoc_vmsg(MANDOCERR_DT_LATE, - mdoc->parse, line, ppos, - "Dt %s", buf + *pos); - return; - } - } else if ( ! (mdoc_macros[tok].flags & MDOC_PROLOGUE)) { - if (mdoc->meta.title == NULL) { - mandoc_vmsg(MANDOCERR_DT_NOTITLE, - mdoc->parse, line, ppos, "%s %s", - mdoc_macronames[tok], buf + *pos); - mdoc->meta.title = mandoc_strdup("UNTITLED"); - } - if (NULL == mdoc->meta.vol) - mdoc->meta.vol = mandoc_strdup("LOCAL"); - mdoc->flags |= MDOC_PBODY; - } - (*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf); -} - - -static void -node_append(struct mdoc *mdoc, struct mdoc_node *p) -{ - - assert(mdoc->last); - assert(mdoc->first); - assert(MDOC_ROOT != p->type); - - switch (mdoc->next) { - case MDOC_NEXT_SIBLING: - mdoc->last->next = p; - p->prev = mdoc->last; - p->parent = mdoc->last->parent; - break; - case MDOC_NEXT_CHILD: - mdoc->last->child = p; - p->parent = mdoc->last; - break; - default: - abort(); - /* NOTREACHED */ - } - - p->parent->nchild++; - - /* - * Copy over the normalised-data pointer of our parent. Not - * everybody has one, but copying a null pointer is fine. - */ - - switch (p->type) { - case MDOC_BODY: - if (ENDBODY_NOT != p->end) - break; - /* FALLTHROUGH */ - case MDOC_TAIL: - /* FALLTHROUGH */ - case MDOC_HEAD: - p->norm = p->parent->norm; - break; - default: - break; - } - - mdoc_valid_pre(mdoc, p); + assert(tok > TOKEN_NONE && tok < MDOC_MAX); - switch (p->type) { - case MDOC_HEAD: - assert(MDOC_BLOCK == p->parent->type); - p->parent->head = p; - break; - case MDOC_TAIL: - assert(MDOC_BLOCK == p->parent->type); - p->parent->tail = p; - break; - case MDOC_BODY: - if (p->end) - break; - assert(MDOC_BLOCK == p->parent->type); - p->parent->body = p; - break; - default: - break; - } - - mdoc->last = p; - - switch (p->type) { - case MDOC_TBL: - /* FALLTHROUGH */ - case MDOC_TEXT: - mdoc_valid_post(mdoc); - break; - default: - break; - } -} - -static struct mdoc_node * -node_alloc(struct mdoc *mdoc, int line, int pos, - enum mdoct tok, enum mdoc_type type) -{ - struct mdoc_node *p; - - p = mandoc_calloc(1, sizeof(struct mdoc_node)); - p->sec = mdoc->lastsec; - p->line = line; - p->pos = pos; - p->tok = tok; - p->type = type; - - /* Flag analysis. */ - - if (MDOC_SYNOPSIS & mdoc->flags) - p->flags |= MDOC_SYNPRETTY; - else - p->flags &= ~MDOC_SYNPRETTY; - if (MDOC_NEWLINE & mdoc->flags) - p->flags |= MDOC_LINE; - mdoc->flags &= ~MDOC_NEWLINE; - - return(p); + (*mdoc_macros[tok].fp)(mdoc, tok, line, ppos, pos, buf); } void -mdoc_tail_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok) +mdoc_tail_alloc(struct roff_man *mdoc, int line, int pos, int tok) { - struct mdoc_node *p; + struct roff_node *p; - p = node_alloc(mdoc, line, pos, tok, MDOC_TAIL); - node_append(mdoc, p); - mdoc->next = MDOC_NEXT_CHILD; + p = roff_node_alloc(mdoc, line, pos, ROFFT_TAIL, tok); + roff_node_append(mdoc, p); + mdoc->next = ROFF_NEXT_CHILD; } -struct mdoc_node * -mdoc_head_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok) +struct roff_node * +mdoc_endbody_alloc(struct roff_man *mdoc, int line, int pos, int tok, + struct roff_node *body, enum mdoc_endbody end) { - struct mdoc_node *p; - - assert(mdoc->first); - assert(mdoc->last); - p = node_alloc(mdoc, line, pos, tok, MDOC_HEAD); - node_append(mdoc, p); - mdoc->next = MDOC_NEXT_CHILD; - return(p); -} - -struct mdoc_node * -mdoc_body_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok) -{ - struct mdoc_node *p; - - p = node_alloc(mdoc, line, pos, tok, MDOC_BODY); - node_append(mdoc, p); - mdoc->next = MDOC_NEXT_CHILD; - return(p); -} - -struct mdoc_node * -mdoc_endbody_alloc(struct mdoc *mdoc, int line, int pos, enum mdoct tok, - struct mdoc_node *body, enum mdoc_endbody end) -{ - struct mdoc_node *p; + struct roff_node *p; body->flags |= MDOC_ENDED; body->parent->flags |= MDOC_ENDED; - p = node_alloc(mdoc, line, pos, tok, MDOC_BODY); + p = roff_node_alloc(mdoc, line, pos, ROFFT_BODY, tok); p->body = body; p->norm = body->norm; p->end = end; - node_append(mdoc, p); - mdoc->next = MDOC_NEXT_SIBLING; - return(p); + roff_node_append(mdoc, p); + mdoc->next = ROFF_NEXT_SIBLING; + return p; } -struct mdoc_node * -mdoc_block_alloc(struct mdoc *mdoc, int line, int pos, - enum mdoct tok, struct mdoc_arg *args) +struct roff_node * +mdoc_block_alloc(struct roff_man *mdoc, int line, int pos, + int tok, struct mdoc_arg *args) { - struct mdoc_node *p; + struct roff_node *p; - p = node_alloc(mdoc, line, pos, tok, MDOC_BLOCK); + p = roff_node_alloc(mdoc, line, pos, ROFFT_BLOCK, tok); p->args = args; if (p->args) (args->refcnt)++; switch (tok) { case MDOC_Bd: - /* FALLTHROUGH */ case MDOC_Bf: - /* FALLTHROUGH */ case MDOC_Bl: - /* FALLTHROUGH */ case MDOC_En: - /* FALLTHROUGH */ case MDOC_Rs: p->norm = mandoc_calloc(1, sizeof(union mdoc_data)); break; default: break; } - node_append(mdoc, p); - mdoc->next = MDOC_NEXT_CHILD; - return(p); + roff_node_append(mdoc, p); + mdoc->next = ROFF_NEXT_CHILD; + return p; } void -mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos, - enum mdoct tok, struct mdoc_arg *args) +mdoc_elem_alloc(struct roff_man *mdoc, int line, int pos, + int tok, struct mdoc_arg *args) { - struct mdoc_node *p; + struct roff_node *p; - p = node_alloc(mdoc, line, pos, tok, MDOC_ELEM); + p = roff_node_alloc(mdoc, line, pos, ROFFT_ELEM, tok); p->args = args; if (p->args) (args->refcnt)++; @@ -479,106 +196,17 @@ mdoc_elem_alloc(struct mdoc *mdoc, int line, int pos, default: break; } - node_append(mdoc, p); - mdoc->next = MDOC_NEXT_CHILD; -} - -void -mdoc_word_alloc(struct mdoc *mdoc, int line, int pos, const char *p) -{ - struct mdoc_node *n; - - n = node_alloc(mdoc, line, pos, MDOC_MAX, MDOC_TEXT); - n->string = roff_strdup(mdoc->roff, p); - node_append(mdoc, n); - mdoc->next = MDOC_NEXT_SIBLING; + roff_node_append(mdoc, p); + mdoc->next = ROFF_NEXT_CHILD; } void -mdoc_word_append(struct mdoc *mdoc, const char *p) +mdoc_node_relink(struct roff_man *mdoc, struct roff_node *p) { - struct mdoc_node *n; - char *addstr, *newstr; - n = mdoc->last; - addstr = roff_strdup(mdoc->roff, p); - mandoc_asprintf(&newstr, "%s %s", n->string, addstr); - free(addstr); - free(n->string); - n->string = newstr; - mdoc->next = MDOC_NEXT_SIBLING; -} - -static void -mdoc_node_free(struct mdoc_node *p) -{ - - if (MDOC_BLOCK == p->type || MDOC_ELEM == p->type) - free(p->norm); - if (p->string) - free(p->string); - if (p->args) - mdoc_argv_free(p->args); - free(p); -} - -static void -mdoc_node_unlink(struct mdoc *mdoc, struct mdoc_node *n) -{ - - /* Adjust siblings. */ - - if (n->prev) - n->prev->next = n->next; - if (n->next) - n->next->prev = n->prev; - - /* Adjust parent. */ - - if (n->parent) { - n->parent->nchild--; - if (n->parent->child == n) - n->parent->child = n->prev ? n->prev : n->next; - if (n->parent->last == n) - n->parent->last = n->prev ? n->prev : NULL; - } - - /* Adjust parse point, if applicable. */ - - if (mdoc && mdoc->last == n) { - if (n->prev) { - mdoc->last = n->prev; - mdoc->next = MDOC_NEXT_SIBLING; - } else { - mdoc->last = n->parent; - mdoc->next = MDOC_NEXT_CHILD; - } - } - - if (mdoc && mdoc->first == n) - mdoc->first = NULL; -} - -void -mdoc_node_delete(struct mdoc *mdoc, struct mdoc_node *p) -{ - - while (p->child) { - assert(p->nchild); - mdoc_node_delete(mdoc, p->child); - } - assert(0 == p->nchild); - - mdoc_node_unlink(mdoc, p); - mdoc_node_free(p); -} - -void -mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p) -{ - - mdoc_node_unlink(mdoc, p); - node_append(mdoc, p); + roff_node_unlink(mdoc, p); + p->prev = p->next = NULL; + roff_node_append(mdoc, p); } /* @@ -586,37 +214,37 @@ mdoc_node_relink(struct mdoc *mdoc, struct mdoc_node *p) * control character. */ static int -mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs) +mdoc_ptext(struct roff_man *mdoc, int line, char *buf, int offs) { + struct roff_node *n; char *c, *ws, *end; - struct mdoc_node *n; assert(mdoc->last); n = mdoc->last; /* * Divert directly to list processing if we're encountering a - * columnar MDOC_BLOCK with or without a prior MDOC_BLOCK entry - * (a MDOC_BODY means it's already open, in which case we should + * columnar ROFFT_BLOCK with or without a prior ROFFT_BLOCK entry + * (a ROFFT_BODY means it's already open, in which case we should * process within its context in the normal way). */ - if (n->tok == MDOC_Bl && n->type == MDOC_BODY && + if (n->tok == MDOC_Bl && n->type == ROFFT_BODY && n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) { /* `Bl' is open without any children. */ mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf); - return(1); + return 1; } - if (MDOC_It == n->tok && MDOC_BLOCK == n->type && + if (n->tok == MDOC_It && n->type == ROFFT_BLOCK && NULL != n->parent && MDOC_Bl == n->parent->tok && LIST_column == n->parent->norm->Bl.type) { /* `Bl' has block-level `It' children. */ mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, line, offs, &offs, buf); - return(1); + return 1; } /* @@ -673,16 +301,16 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs) * blank lines aren't allowed, but enough manuals assume this * behaviour that we want to work around it. */ - mdoc_elem_alloc(mdoc, line, offs, MDOC_sp, NULL); - mdoc->next = MDOC_NEXT_SIBLING; - mdoc_valid_post(mdoc); - return(1); + roff_elem_alloc(mdoc, line, offs, MDOC_sp); + mdoc->last->flags |= MDOC_VALID | MDOC_ENDED; + mdoc->next = ROFF_NEXT_SIBLING; + return 1; } - mdoc_word_alloc(mdoc, line, offs, buf+offs); + roff_word_alloc(mdoc, line, offs, buf+offs); if (mdoc->flags & MDOC_LITERAL) - return(1); + return 1; /* * End-of-sentence check. If the last character is an unescaped @@ -694,7 +322,7 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs) if (mandoc_eos(buf+offs, (size_t)(end-buf-offs))) mdoc->last->flags |= MDOC_EOS; - return(1); + return 1; } /* @@ -702,11 +330,11 @@ mdoc_ptext(struct mdoc *mdoc, int line, char *buf, int offs) * character. */ static int -mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) +mdoc_pmacro(struct roff_man *mdoc, int ln, char *buf, int offs) { - struct mdoc_node *n; + struct roff_node *n; const char *cp; - enum mdoct tok; + int tok; int i, sv; char mac[5]; @@ -723,12 +351,12 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) mac[i] = '\0'; - tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : MDOC_MAX; + tok = (i > 1 && i < 4) ? mdoc_hash_find(mac) : TOKEN_NONE; - if (tok == MDOC_MAX) { + if (tok == TOKEN_NONE) { mandoc_msg(MANDOCERR_MACRO, mdoc->parse, ln, sv, buf + sv - 1); - return(1); + return 1; } /* Skip a leading escape sequence or tab. */ @@ -767,7 +395,7 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) if (NULL == mdoc->last || MDOC_It == tok || MDOC_El == tok) { mdoc_macro(mdoc, tok, ln, sv, &offs, buf); - return(1); + return 1; } n = mdoc->last; @@ -778,11 +406,11 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) * context around the parsed macro. */ - if (n->tok == MDOC_Bl && n->type == MDOC_BODY && + if (n->tok == MDOC_Bl && n->type == ROFFT_BODY && n->end == ENDBODY_NOT && n->norm->Bl.type == LIST_column) { mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); - return(1); + return 1; } /* @@ -791,13 +419,13 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) * then open an `It' block context around the parsed macro. */ - if (MDOC_It == n->tok && MDOC_BLOCK == n->type && + if (n->tok == MDOC_It && n->type == ROFFT_BLOCK && NULL != n->parent && MDOC_Bl == n->parent->tok && LIST_column == n->parent->norm->Bl.type) { mdoc->flags |= MDOC_FREECOL; mdoc_macro(mdoc, MDOC_It, ln, sv, &sv, buf); - return(1); + return 1; } /* Normal processing of a macro. */ @@ -808,9 +436,9 @@ mdoc_pmacro(struct mdoc *mdoc, int ln, char *buf, int offs) if (mdoc->quick && MDOC_Sh == tok && SEC_NAME != mdoc->last->sec) - return(2); + return 2; - return(1); + return 1; } enum mdelim @@ -818,82 +446,44 @@ mdoc_isdelim(const char *p) { if ('\0' == p[0]) - return(DELIM_NONE); + return DELIM_NONE; if ('\0' == p[1]) switch (p[0]) { case '(': - /* FALLTHROUGH */ case '[': - return(DELIM_OPEN); + return DELIM_OPEN; case '|': - return(DELIM_MIDDLE); + return DELIM_MIDDLE; case '.': - /* FALLTHROUGH */ case ',': - /* FALLTHROUGH */ case ';': - /* FALLTHROUGH */ case ':': - /* FALLTHROUGH */ case '?': - /* FALLTHROUGH */ case '!': - /* FALLTHROUGH */ case ')': - /* FALLTHROUGH */ case ']': - return(DELIM_CLOSE); + return DELIM_CLOSE; default: - return(DELIM_NONE); + return DELIM_NONE; } if ('\\' != p[0]) - return(DELIM_NONE); + return DELIM_NONE; if (0 == strcmp(p + 1, ".")) - return(DELIM_CLOSE); + return DELIM_CLOSE; if (0 == strcmp(p + 1, "fR|\\fP")) - return(DELIM_MIDDLE); + return DELIM_MIDDLE; - return(DELIM_NONE); + return DELIM_NONE; } void -mdoc_deroff(char **dest, const struct mdoc_node *n) +mdoc_validate(struct roff_man *mdoc) { - char *cp; - size_t sz; - - if (MDOC_TEXT != n->type) { - for (n = n->child; n; n = n->next) - mdoc_deroff(dest, n); - return; - } - - /* Skip leading whitespace. */ - - for (cp = n->string; '\0' != *cp; cp++) - if (0 == isspace((unsigned char)*cp)) - break; - - /* Skip trailing whitespace. */ - - for (sz = strlen(cp); sz; sz--) - if (0 == isspace((unsigned char)cp[sz-1])) - break; - - /* Skip empty strings. */ - - if (0 == sz) - return; - - if (NULL == *dest) { - *dest = mandoc_strndup(cp, sz); - return; - } - mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp); - free(*dest); - *dest = cp; + mdoc->last = mdoc->first; + mdoc_node_validate(mdoc); + mdoc_state_reset(mdoc); } diff --git a/usr/src/cmd/mandoc/mdoc.h b/usr/src/cmd/mandoc/mdoc.h index e45786d4aa..ebe4391ef6 100644 --- a/usr/src/cmd/mandoc/mdoc.h +++ b/usr/src/cmd/mandoc/mdoc.h @@ -1,4 +1,4 @@ -/* $Id: mdoc.h,v 1.136 2015/02/12 12:24:33 schwarze Exp $ */ +/* $Id: mdoc.h,v 1.144 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,141 +7,139 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -enum mdoct { - MDOC_Ap = 0, - MDOC_Dd, - MDOC_Dt, - MDOC_Os, - MDOC_Sh, - MDOC_Ss, - MDOC_Pp, - MDOC_D1, - MDOC_Dl, - MDOC_Bd, - MDOC_Ed, - MDOC_Bl, - MDOC_El, - MDOC_It, - MDOC_Ad, - MDOC_An, - MDOC_Ar, - MDOC_Cd, - MDOC_Cm, - MDOC_Dv, - MDOC_Er, - MDOC_Ev, - MDOC_Ex, - MDOC_Fa, - MDOC_Fd, - MDOC_Fl, - MDOC_Fn, - MDOC_Ft, - MDOC_Ic, - MDOC_In, - MDOC_Li, - MDOC_Nd, - MDOC_Nm, - MDOC_Op, - MDOC_Ot, - MDOC_Pa, - MDOC_Rv, - MDOC_St, - MDOC_Va, - MDOC_Vt, - MDOC_Xr, - MDOC__A, - MDOC__B, - MDOC__D, - MDOC__I, - MDOC__J, - MDOC__N, - MDOC__O, - MDOC__P, - MDOC__R, - MDOC__T, - MDOC__V, - MDOC_Ac, - MDOC_Ao, - MDOC_Aq, - MDOC_At, - MDOC_Bc, - MDOC_Bf, - MDOC_Bo, - MDOC_Bq, - MDOC_Bsx, - MDOC_Bx, - MDOC_Db, - MDOC_Dc, - MDOC_Do, - MDOC_Dq, - MDOC_Ec, - MDOC_Ef, - MDOC_Em, - MDOC_Eo, - MDOC_Fx, - MDOC_Ms, - MDOC_No, - MDOC_Ns, - MDOC_Nx, - MDOC_Ox, - MDOC_Pc, - MDOC_Pf, - MDOC_Po, - MDOC_Pq, - MDOC_Qc, - MDOC_Ql, - MDOC_Qo, - MDOC_Qq, - MDOC_Re, - MDOC_Rs, - MDOC_Sc, - MDOC_So, - MDOC_Sq, - MDOC_Sm, - MDOC_Sx, - MDOC_Sy, - MDOC_Tn, - MDOC_Ux, - MDOC_Xc, - MDOC_Xo, - MDOC_Fo, - MDOC_Fc, - MDOC_Oo, - MDOC_Oc, - MDOC_Bk, - MDOC_Ek, - MDOC_Bt, - MDOC_Hf, - MDOC_Fr, - MDOC_Ud, - MDOC_Lb, - MDOC_Lp, - MDOC_Lk, - MDOC_Mt, - MDOC_Brq, - MDOC_Bro, - MDOC_Brc, - MDOC__C, - MDOC_Es, - MDOC_En, - MDOC_Dx, - MDOC__Q, - MDOC_br, - MDOC_sp, - MDOC__U, - MDOC_Ta, - MDOC_ll, - MDOC_MAX -}; +#define MDOC_Ap 0 +#define MDOC_Dd 1 +#define MDOC_Dt 2 +#define MDOC_Os 3 +#define MDOC_Sh 4 +#define MDOC_Ss 5 +#define MDOC_Pp 6 +#define MDOC_D1 7 +#define MDOC_Dl 8 +#define MDOC_Bd 9 +#define MDOC_Ed 10 +#define MDOC_Bl 11 +#define MDOC_El 12 +#define MDOC_It 13 +#define MDOC_Ad 14 +#define MDOC_An 15 +#define MDOC_Ar 16 +#define MDOC_Cd 17 +#define MDOC_Cm 18 +#define MDOC_Dv 19 +#define MDOC_Er 20 +#define MDOC_Ev 21 +#define MDOC_Ex 22 +#define MDOC_Fa 23 +#define MDOC_Fd 24 +#define MDOC_Fl 25 +#define MDOC_Fn 26 +#define MDOC_Ft 27 +#define MDOC_Ic 28 +#define MDOC_In 29 +#define MDOC_Li 30 +#define MDOC_Nd 31 +#define MDOC_Nm 32 +#define MDOC_Op 33 +#define MDOC_Ot 34 +#define MDOC_Pa 35 +#define MDOC_Rv 36 +#define MDOC_St 37 +#define MDOC_Va 38 +#define MDOC_Vt 39 +#define MDOC_Xr 40 +#define MDOC__A 41 +#define MDOC__B 42 +#define MDOC__D 43 +#define MDOC__I 44 +#define MDOC__J 45 +#define MDOC__N 46 +#define MDOC__O 47 +#define MDOC__P 48 +#define MDOC__R 49 +#define MDOC__T 50 +#define MDOC__V 51 +#define MDOC_Ac 52 +#define MDOC_Ao 53 +#define MDOC_Aq 54 +#define MDOC_At 55 +#define MDOC_Bc 56 +#define MDOC_Bf 57 +#define MDOC_Bo 58 +#define MDOC_Bq 59 +#define MDOC_Bsx 60 +#define MDOC_Bx 61 +#define MDOC_Db 62 +#define MDOC_Dc 63 +#define MDOC_Do 64 +#define MDOC_Dq 65 +#define MDOC_Ec 66 +#define MDOC_Ef 67 +#define MDOC_Em 68 +#define MDOC_Eo 69 +#define MDOC_Fx 70 +#define MDOC_Ms 71 +#define MDOC_No 72 +#define MDOC_Ns 73 +#define MDOC_Nx 74 +#define MDOC_Ox 75 +#define MDOC_Pc 76 +#define MDOC_Pf 77 +#define MDOC_Po 78 +#define MDOC_Pq 79 +#define MDOC_Qc 80 +#define MDOC_Ql 81 +#define MDOC_Qo 82 +#define MDOC_Qq 83 +#define MDOC_Re 84 +#define MDOC_Rs 85 +#define MDOC_Sc 86 +#define MDOC_So 87 +#define MDOC_Sq 88 +#define MDOC_Sm 89 +#define MDOC_Sx 90 +#define MDOC_Sy 91 +#define MDOC_Tn 92 +#define MDOC_Ux 93 +#define MDOC_Xc 94 +#define MDOC_Xo 95 +#define MDOC_Fo 96 +#define MDOC_Fc 97 +#define MDOC_Oo 98 +#define MDOC_Oc 99 +#define MDOC_Bk 100 +#define MDOC_Ek 101 +#define MDOC_Bt 102 +#define MDOC_Hf 103 +#define MDOC_Fr 104 +#define MDOC_Ud 105 +#define MDOC_Lb 106 +#define MDOC_Lp 107 +#define MDOC_Lk 108 +#define MDOC_Mt 109 +#define MDOC_Brq 110 +#define MDOC_Bro 111 +#define MDOC_Brc 112 +#define MDOC__C 113 +#define MDOC_Es 114 +#define MDOC_En 115 +#define MDOC_Dx 116 +#define MDOC__Q 117 +#define MDOC_br 118 +#define MDOC_sp 119 +#define MDOC__U 120 +#define MDOC_Ta 121 +#define MDOC_ll 122 +#define MDOC_MAX 123 enum mdocargt { MDOC_Split, /* -split */ @@ -174,61 +172,6 @@ enum mdocargt { MDOC_ARG_MAX }; -enum mdoc_type { - MDOC_TEXT, - MDOC_ELEM, - MDOC_HEAD, - MDOC_TAIL, - MDOC_BODY, - MDOC_BLOCK, - MDOC_TBL, - MDOC_EQN, - MDOC_ROOT -}; - -/* - * Section (named/unnamed) of `Sh'. Note that these appear in the - * conventional order imposed by mdoc.7. In the case of SEC_NONE, no - * section has been invoked (this shouldn't happen). SEC_CUSTOM refers - * to other sections. - */ -enum mdoc_sec { - SEC_NONE = 0, - SEC_NAME, /* NAME */ - SEC_LIBRARY, /* LIBRARY */ - SEC_SYNOPSIS, /* SYNOPSIS */ - SEC_DESCRIPTION, /* DESCRIPTION */ - SEC_CONTEXT, /* CONTEXT */ - SEC_IMPLEMENTATION, /* IMPLEMENTATION NOTES */ - SEC_RETURN_VALUES, /* RETURN VALUES */ - SEC_ENVIRONMENT, /* ENVIRONMENT */ - SEC_FILES, /* FILES */ - SEC_EXIT_STATUS, /* EXIT STATUS */ - SEC_EXAMPLES, /* EXAMPLES */ - SEC_DIAGNOSTICS, /* DIAGNOSTICS */ - SEC_COMPATIBILITY, /* COMPATIBILITY */ - SEC_ERRORS, /* ERRORS */ - SEC_SEE_ALSO, /* SEE ALSO */ - SEC_STANDARDS, /* STANDARDS */ - SEC_HISTORY, /* HISTORY */ - SEC_AUTHORS, /* AUTHORS */ - SEC_CAVEATS, /* CAVEATS */ - SEC_BUGS, /* BUGS */ - SEC_SECURITY, /* SECURITY */ - SEC_CUSTOM, - SEC__MAX -}; - -struct mdoc_meta { - char *msec; /* `Dt' section (1, 3p, etc.) */ - char *vol; /* `Dt' volume (implied) */ - char *arch; /* `Dt' arch (i386, etc.) */ - char *date; /* `Dd' normalised date */ - char *title; /* `Dt' title (FOO, etc.) */ - char *os; /* `Os' system (OpenBSD, etc.) */ - char *name; /* leading `Nm' name */ -}; - /* * An argument to a macro (multiple values = `-column xxx yyy'). */ @@ -251,16 +194,6 @@ struct mdoc_arg { unsigned int refcnt; }; -/* - * Indicates that a BODY's formatting has ended, but the scope is still - * open. Used for syntax-broken blocks. - */ -enum mdoc_endbody { - ENDBODY_NOT = 0, - ENDBODY_SPACE, /* is broken: append a space */ - ENDBODY_NOSPACE /* is broken: don't append a space */ -}; - enum mdoc_list { LIST__NONE = 0, LIST_bullet, /* -bullet */ @@ -337,59 +270,15 @@ union mdoc_data { struct mdoc_bd Bd; struct mdoc_bf Bf; struct mdoc_bl Bl; - struct mdoc_node *Es; + struct roff_node *Es; struct mdoc_rs Rs; }; -/* - * Single node in tree-linked AST. - */ -struct mdoc_node { - struct mdoc_node *parent; /* parent AST node */ - struct mdoc_node *child; /* first child AST node */ - struct mdoc_node *last; /* last child AST node */ - struct mdoc_node *next; /* sibling AST node */ - struct mdoc_node *prev; /* prior sibling AST node */ - int nchild; /* number children */ - int line; /* parse line */ - int pos; /* parse column */ - enum mdoct tok; /* tok or MDOC__MAX if none */ - int flags; -#define MDOC_VALID (1 << 0) /* has been validated */ -#define MDOC_ENDED (1 << 1) /* gone past body end mark */ -#define MDOC_EOS (1 << 2) /* at sentence boundary */ -#define MDOC_LINE (1 << 3) /* first macro/text on line */ -#define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting */ -#define MDOC_BROKEN (1 << 5) /* must validate parent when ending */ -#define MDOC_DELIMO (1 << 6) -#define MDOC_DELIMC (1 << 7) - enum mdoc_type type; /* AST node type */ - enum mdoc_sec sec; /* current named section */ - union mdoc_data *norm; /* normalised args */ - int prev_font; /* before entering this node */ - /* FIXME: these can be union'd to shave a few bytes. */ - struct mdoc_arg *args; /* BLOCK/ELEM */ - struct mdoc_node *head; /* BLOCK */ - struct mdoc_node *body; /* BLOCK/ENDBODY */ - struct mdoc_node *tail; /* BLOCK */ - char *string; /* TEXT */ - const struct tbl_span *span; /* TBL */ - const struct eqn *eqn; /* EQN */ - enum mdoc_endbody end; /* BODY */ -}; - -/* Names of macros. Index is enum mdoct. */ +/* Names of macros. */ extern const char *const *mdoc_macronames; /* Names of macro args. Index is enum mdocargt. */ extern const char *const *mdoc_argnames; -__BEGIN_DECLS - -struct mdoc; - -const struct mdoc_node *mdoc_node(const struct mdoc *); -const struct mdoc_meta *mdoc_meta(const struct mdoc *); -void mdoc_deroff(char **, const struct mdoc_node *); -__END_DECLS +void mdoc_validate(struct roff_man *); diff --git a/usr/src/cmd/mandoc/mdoc_argv.c b/usr/src/cmd/mandoc/mdoc_argv.c index a53389bf99..8675bdb2db 100644 --- a/usr/src/cmd/mandoc/mdoc_argv.c +++ b/usr/src/cmd/mandoc/mdoc_argv.c @@ -1,15 +1,15 @@ -/* $Id: mdoc_argv.c,v 1.100 2015/02/04 18:59:45 schwarze Exp $ */ +/* $Id: mdoc_argv.c,v 1.107 2015/10/17 00:21:07 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2012, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -24,11 +24,12 @@ #include <stdio.h> #include <string.h> -#include "mdoc.h" -#include "mandoc.h" #include "mandoc_aux.h" -#include "libmdoc.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" #include "libmandoc.h" +#include "libmdoc.h" #define MULTI_STEP 5 /* pre-allocate argument values */ #define DELIMSZ 6 /* max possible size of a delimiter */ @@ -51,12 +52,12 @@ struct mdocarg { }; static void argn_free(struct mdoc_arg *, int); -static enum margserr args(struct mdoc *, int, int *, +static enum margserr args(struct roff_man *, int, int *, char *, enum argsflag, char **); static int args_checkpunct(const char *, int); -static void argv_multi(struct mdoc *, int, +static void argv_multi(struct roff_man *, int, struct mdoc_argv *, int *, char *); -static void argv_single(struct mdoc *, int, +static void argv_single(struct roff_man *, int, struct mdoc_argv *, int *, char *); static const enum argvflag argvflags[MDOC_ARG_MAX] = { @@ -275,7 +276,7 @@ static const struct mdocarg mdocargs[MDOC_MAX] = { * Some flags take no argument, some one, some multiple. */ void -mdoc_argv(struct mdoc *mdoc, int line, enum mdoct tok, +mdoc_argv(struct roff_man *mdoc, int line, int tok, struct mdoc_arg **reta, int *pos, char *buf) { struct mdoc_argv tmpv; @@ -412,18 +413,18 @@ argn_free(struct mdoc_arg *p, int iarg) } enum margserr -mdoc_args(struct mdoc *mdoc, int line, int *pos, - char *buf, enum mdoct tok, char **v) +mdoc_args(struct roff_man *mdoc, int line, int *pos, + char *buf, int tok, char **v) { - struct mdoc_node *n; + struct roff_node *n; char *v_local; enum argsflag fl; if (v == NULL) v = &v_local; - fl = tok == MDOC_MAX ? ARGSFL_NONE : mdocargs[tok].flags; + fl = tok == TOKEN_NONE ? ARGSFL_NONE : mdocargs[tok].flags; if (tok != MDOC_It) - return(args(mdoc, line, pos, buf, fl, v)); + return args(mdoc, line, pos, buf, fl, v); /* * We know that we're in an `It', so it's reasonable to expect @@ -439,105 +440,82 @@ mdoc_args(struct mdoc *mdoc, int line, int *pos, break; } - return(args(mdoc, line, pos, buf, fl, v)); + return args(mdoc, line, pos, buf, fl, v); } static enum margserr -args(struct mdoc *mdoc, int line, int *pos, +args(struct roff_man *mdoc, int line, int *pos, char *buf, enum argsflag fl, char **v) { - char *p, *pp; + char *p; int pairs; - enum margserr rc; - if ('\0' == buf[*pos]) { - if (MDOC_PPHRASE & mdoc->flags) - return(ARGS_EOLN); - /* - * If we're not in a partial phrase and the flag for - * being a phrase literal is still set, the punctuation - * is unterminated. - */ - if (MDOC_PHRASELIT & mdoc->flags) + if (buf[*pos] == '\0') { + if (mdoc->flags & MDOC_PHRASELIT && + ! (mdoc->flags & MDOC_PHRASE)) { mandoc_msg(MANDOCERR_ARG_QUOTE, mdoc->parse, line, *pos, NULL); - - mdoc->flags &= ~MDOC_PHRASELIT; - return(ARGS_EOLN); + mdoc->flags &= ~MDOC_PHRASELIT; + } + return ARGS_EOLN; } - *v = &buf[*pos]; + *v = buf + *pos; - if (ARGSFL_DELIM == fl) - if (args_checkpunct(buf, *pos)) - return(ARGS_PUNCT); + if (fl == ARGSFL_DELIM && args_checkpunct(buf, *pos)) + return ARGS_PUNCT; /* - * First handle TABSEP items, restricted to `Bl -column'. This - * ignores conventional token parsing and instead uses tabs or - * `Ta' macros to separate phrases. Phrases are parsed again - * for arguments at a later phase. + * Tabs in `It' lines in `Bl -column' can't be escaped. + * Phrases are reparsed for `Ta' and other macros later. */ - if (ARGSFL_TABSEP == fl) { - /* Scan ahead to tab (can't be escaped). */ - p = strchr(*v, '\t'); - pp = NULL; - - /* Scan ahead to unescaped `Ta'. */ - if ( ! (MDOC_PHRASELIT & mdoc->flags)) - for (pp = *v; ; pp++) { - if (NULL == (pp = strstr(pp, "Ta"))) - break; - if (pp > *v && ' ' != *(pp - 1)) - continue; - if (' ' == *(pp + 2) || '\0' == *(pp + 2)) - break; - } - - /* By default, assume a phrase. */ - rc = ARGS_PHRASE; - - /* - * Adjust new-buffer position to be beyond delimiter - * mark (e.g., Ta -> end + 2). - */ - if (p && pp) { - *pos += pp < p ? 2 : 1; - rc = pp < p ? ARGS_PHRASE : ARGS_PPHRASE; - p = pp < p ? pp : p; - } else if (p && ! pp) { - rc = ARGS_PPHRASE; - *pos += 1; - } else if (pp && ! p) { - p = pp; - *pos += 2; + if (fl == ARGSFL_TABSEP) { + if ((p = strchr(*v, '\t')) != NULL) { + + /* + * Words right before and right after + * tab characters are not parsed, + * unless there is a blank in between. + */ + + if (p[-1] != ' ') + mdoc->flags |= MDOC_PHRASEQL; + if (p[1] != ' ') + mdoc->flags |= MDOC_PHRASEQN; + + /* + * One or more blanks after a tab cause + * one leading blank in the next column. + * So skip all but one of them. + */ + + *pos += (int)(p - *v) + 1; + while (buf[*pos] == ' ' && buf[*pos + 1] == ' ') + (*pos)++; + + /* + * A tab at the end of an input line + * switches to the next column. + */ + + if (buf[*pos] == '\0' || buf[*pos + 1] == '\0') + mdoc->flags |= MDOC_PHRASEQN; } else { - rc = ARGS_PEND; - p = strchr(*v, 0); + p = strchr(*v, '\0'); + if (p[-1] == ' ') + mandoc_msg(MANDOCERR_SPACE_EOL, + mdoc->parse, line, *pos, NULL); + *pos += (int)(p - *v); } - /* Whitespace check for eoln case... */ - if ('\0' == *p && ' ' == *(p - 1)) - mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, - line, *pos, NULL); - - *pos += (int)(p - *v); - - /* Strip delimiter's preceding whitespace. */ - pp = p - 1; - while (pp > *v && ' ' == *pp) { - if (pp > *v && '\\' == *(pp - 1)) - break; - pp--; - } - *(pp + 1) = 0; + /* Skip any trailing blank characters. */ + while (p > *v && p[-1] == ' ' && + (p - 1 == *v || p[-2] != '\\')) + p--; + *p = '\0'; - /* Strip delimiter's proceeding whitespace. */ - for (pp = &buf[*pos]; ' ' == *pp; pp++, (*pos)++) - /* Skip ahead. */ ; - - return(rc); + return ARGS_PHRASE; } /* @@ -548,11 +526,11 @@ args(struct mdoc *mdoc, int line, int *pos, * Whitespace is NOT involved in literal termination. */ - if (MDOC_PHRASELIT & mdoc->flags || '\"' == buf[*pos]) { - if ( ! (MDOC_PHRASELIT & mdoc->flags)) + if (mdoc->flags & MDOC_PHRASELIT || buf[*pos] == '\"') { + if ( ! (mdoc->flags & MDOC_PHRASELIT)) *v = &buf[++(*pos)]; - if (MDOC_PPHRASE & mdoc->flags) + if (mdoc->flags & MDOC_PHRASE) mdoc->flags |= MDOC_PHRASELIT; pairs = 0; @@ -572,19 +550,18 @@ args(struct mdoc *mdoc, int line, int *pos, if (pairs) buf[*pos - pairs] = '\0'; - if ('\0' == buf[*pos]) { - if (MDOC_PPHRASE & mdoc->flags) - return(ARGS_QWORD); - mandoc_msg(MANDOCERR_ARG_QUOTE, - mdoc->parse, line, *pos, NULL); - return(ARGS_QWORD); + if (buf[*pos] == '\0') { + if ( ! (mdoc->flags & MDOC_PHRASE)) + mandoc_msg(MANDOCERR_ARG_QUOTE, + mdoc->parse, line, *pos, NULL); + return ARGS_QWORD; } mdoc->flags &= ~MDOC_PHRASELIT; buf[(*pos)++] = '\0'; if ('\0' == buf[*pos]) - return(ARGS_QWORD); + return ARGS_QWORD; while (' ' == buf[*pos]) (*pos)++; @@ -593,13 +570,22 @@ args(struct mdoc *mdoc, int line, int *pos, mandoc_msg(MANDOCERR_SPACE_EOL, mdoc->parse, line, *pos, NULL); - return(ARGS_QWORD); + return ARGS_QWORD; } p = &buf[*pos]; *v = mandoc_getarg(mdoc->parse, &p, line, pos); - return(ARGS_WORD); + /* + * After parsing the last word in this phrase, + * tell lookup() whether or not to interpret it. + */ + + if (*p == '\0' && mdoc->flags & MDOC_PHRASEQL) { + mdoc->flags &= ~MDOC_PHRASEQL; + mdoc->flags |= MDOC_PHRASEQF; + } + return ARGS_WORD; } /* @@ -621,11 +607,11 @@ args_checkpunct(const char *buf, int i) dbuf[j] = buf[i]; if (DELIMSZ == j) - return(0); + return 0; dbuf[j] = '\0'; if (DELIM_CLOSE != mdoc_isdelim(dbuf)) - return(0); + return 0; while (' ' == buf[i]) i++; @@ -638,22 +624,22 @@ args_checkpunct(const char *buf, int i) dbuf[j++] = buf[i++]; if (DELIMSZ == j) - return(0); + return 0; dbuf[j] = '\0'; d = mdoc_isdelim(dbuf); if (DELIM_NONE == d || DELIM_OPEN == d) - return(0); + return 0; while (' ' == buf[i]) i++; } - return('\0' == buf[i]); + return '\0' == buf[i]; } static void -argv_multi(struct mdoc *mdoc, int line, +argv_multi(struct roff_man *mdoc, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; @@ -675,7 +661,7 @@ argv_multi(struct mdoc *mdoc, int line, } static void -argv_single(struct mdoc *mdoc, int line, +argv_single(struct roff_man *mdoc, int line, struct mdoc_argv *v, int *pos, char *buf) { enum margserr ac; diff --git a/usr/src/cmd/mandoc/mdoc_hash.c b/usr/src/cmd/mandoc/mdoc_hash.c index 5e34fe8f58..476116d792 100644 --- a/usr/src/cmd/mandoc/mdoc_hash.c +++ b/usr/src/cmd/mandoc/mdoc_hash.c @@ -1,6 +1,7 @@ -/* $Id: mdoc_hash.c,v 1.21 2014/08/10 23:54:41 schwarze Exp $ */ +/* $Id: mdoc_hash.c,v 1.26 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,22 +26,22 @@ #include <stdio.h> #include <string.h> +#include "roff.h" #include "mdoc.h" #include "libmdoc.h" static unsigned char table[27 * 12]; -/* - * XXX - this hash has global scope, so if intended for use as a library - * with multiple callers, it will need re-invocation protection. - */ void mdoc_hash_init(void) { int i, j, major; const char *p; + if (*table != '\0') + return; + memset(table, UCHAR_MAX, sizeof(table)); for (i = 0; i < (int)MDOC_MAX; i++) { @@ -61,32 +62,32 @@ mdoc_hash_init(void) } } -enum mdoct +int mdoc_hash_find(const char *p) { int major, i, j; if (0 == p[0]) - return(MDOC_MAX); + return TOKEN_NONE; if ( ! isalpha((unsigned char)p[0]) && '%' != p[0]) - return(MDOC_MAX); + return TOKEN_NONE; if (isalpha((unsigned char)p[1])) major = 12 * (tolower((unsigned char)p[1]) - 97); else if ('1' == p[1]) major = 12 * 26; else - return(MDOC_MAX); + return TOKEN_NONE; if (p[2] && p[3]) - return(MDOC_MAX); + return TOKEN_NONE; for (j = 0; j < 12; j++) { if (UCHAR_MAX == (i = table[major + j])) break; if (0 == strcmp(p, mdoc_macronames[i])) - return((enum mdoct)i); + return i; } - return(MDOC_MAX); + return TOKEN_NONE; } diff --git a/usr/src/cmd/mandoc/mdoc_html.c b/usr/src/cmd/mandoc/mdoc_html.c index fba7fb6fa4..8e21bc7963 100644 --- a/usr/src/cmd/mandoc/mdoc_html.c +++ b/usr/src/cmd/mandoc/mdoc_html.c @@ -1,15 +1,15 @@ -/* $Id: mdoc_html.c,v 1.226 2015/03/03 21:11:34 schwarze Exp $ */ +/* $Id: mdoc_html.c,v 1.240 2016/01/08 17:48:09 schwarze Exp $ */ /* * Copyright (c) 2008-2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2014, 2015, 2016 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -27,6 +27,7 @@ #include <unistd.h> #include "mandoc_aux.h" +#include "roff.h" #include "mdoc.h" #include "out.h" #include "html.h" @@ -34,8 +35,8 @@ #define INDENT 5 -#define MDOC_ARGS const struct mdoc_meta *meta, \ - struct mdoc_node *n, \ +#define MDOC_ARGS const struct roff_meta *meta, \ + struct roff_node *n, \ struct html *h #ifndef MIN @@ -47,12 +48,11 @@ struct htmlmdoc { void (*post)(MDOC_ARGS); }; -static void print_mdoc(MDOC_ARGS); static void print_mdoc_head(MDOC_ARGS); static void print_mdoc_node(MDOC_ARGS); static void print_mdoc_nodelist(MDOC_ARGS); static void synopsis_pre(struct html *, - const struct mdoc_node *); + const struct roff_node *); static void a2width(const char *, struct roffsu *); @@ -263,15 +263,6 @@ static const char * const lists[LIST_MAX] = { }; -void -html_mdoc(void *arg, const struct mdoc *mdoc) -{ - - print_mdoc(mdoc_meta(mdoc), mdoc_node(mdoc)->child, - (struct html *)arg); - putchar('\n'); -} - /* * Calculate the scaling unit passed in a `-width' argument. This uses * either a native scaling unit (e.g., 1i, 2m) or the string length of @@ -292,7 +283,7 @@ a2width(const char *p, struct roffsu *su) * See the same function in mdoc_term.c for documentation. */ static void -synopsis_pre(struct html *h, const struct mdoc_node *n) +synopsis_pre(struct html *h, const struct roff_node *n) { if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags)) @@ -308,13 +299,9 @@ synopsis_pre(struct html *h, const struct mdoc_node *n) switch (n->prev->tok) { case MDOC_Fd: - /* FALLTHROUGH */ case MDOC_Fn: - /* FALLTHROUGH */ case MDOC_Fo: - /* FALLTHROUGH */ case MDOC_In: - /* FALLTHROUGH */ case MDOC_Vt: print_paragraph(h); break; @@ -330,27 +317,32 @@ synopsis_pre(struct html *h, const struct mdoc_node *n) } } -static void -print_mdoc(MDOC_ARGS) +void +html_mdoc(void *arg, const struct roff_man *mdoc) { - struct tag *t, *tt; struct htmlpair tag; + struct html *h; + struct tag *t, *tt; PAIR_CLASS_INIT(&tag, "mandoc"); + h = (struct html *)arg; if ( ! (HTML_FRAGMENT & h->oflags)) { print_gen_decls(h); t = print_otag(h, TAG_HTML, 0, NULL); tt = print_otag(h, TAG_HEAD, 0, NULL); - print_mdoc_head(meta, n, h); + print_mdoc_head(&mdoc->meta, mdoc->first->child, h); print_tagq(h, tt); print_otag(h, TAG_BODY, 0, NULL); print_otag(h, TAG_DIV, 1, &tag); } else t = print_otag(h, TAG_DIV, 1, &tag); - print_mdoc_nodelist(meta, n, h); + mdoc_root_pre(&mdoc->meta, mdoc->first->child, h); + print_mdoc_nodelist(&mdoc->meta, mdoc->first->child, h); + mdoc_root_post(&mdoc->meta, mdoc->first->child, h); print_tagq(h, t); + putchar('\n'); } static void @@ -390,10 +382,7 @@ print_mdoc_node(MDOC_ARGS) n->flags &= ~MDOC_ENDED; switch (n->type) { - case MDOC_ROOT: - child = mdoc_root_pre(meta, n, h); - break; - case MDOC_TEXT: + case ROFFT_TEXT: /* No tables in this mode... */ assert(NULL == h->tblt); @@ -410,12 +399,12 @@ print_mdoc_node(MDOC_ARGS) if (MDOC_DELIMO & n->flags) h->flags |= HTML_NOSPACE; return; - case MDOC_EQN: + case ROFFT_EQN: if (n->flags & MDOC_LINE) putchar('\n'); print_eqn(h, n->eqn); break; - case MDOC_TBL: + case ROFFT_TBL: /* * This will take care of initialising all of the table * state data for the first table, then tearing it down @@ -450,10 +439,7 @@ print_mdoc_node(MDOC_ARGS) print_stagq(h, t); switch (n->type) { - case MDOC_ROOT: - mdoc_root_post(meta, n, h); - break; - case MDOC_EQN: + case ROFFT_EQN: break; default: if ( ! mdocs[n->tok].post || n->flags & MDOC_ENDED) @@ -534,7 +520,7 @@ mdoc_root_pre(MDOC_ARGS) free(title); free(volume); - return(1); + return 1; } static int @@ -543,22 +529,21 @@ mdoc_sh_pre(MDOC_ARGS) struct htmlpair tag; switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: PAIR_CLASS_INIT(&tag, "section"); print_otag(h, TAG_DIV, 1, &tag); - return(1); - case MDOC_BODY: + return 1; + case ROFFT_BODY: if (n->sec == SEC_AUTHORS) h->flags &= ~(HTML_SPLIT|HTML_NOSPLIT); - return(1); + return 1; default: break; } bufinit(h); - bufcat(h, "x"); - for (n = n->child; n && MDOC_TEXT == n->type; ) { + for (n = n->child; n != NULL && n->type == ROFFT_TEXT; ) { bufcat_id(h, n->string); if (NULL != (n = n->next)) bufcat_id(h, " "); @@ -570,7 +555,7 @@ mdoc_sh_pre(MDOC_ARGS) } else print_otag(h, TAG_H1, 0, NULL); - return(1); + return 1; } static int @@ -578,17 +563,16 @@ mdoc_ss_pre(MDOC_ARGS) { struct htmlpair tag; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { PAIR_CLASS_INIT(&tag, "subsection"); print_otag(h, TAG_DIV, 1, &tag); - return(1); - } else if (MDOC_BODY == n->type) - return(1); + return 1; + } else if (n->type == ROFFT_BODY) + return 1; bufinit(h); - bufcat(h, "x"); - for (n = n->child; n && MDOC_TEXT == n->type; ) { + for (n = n->child; n != NULL && n->type == ROFFT_TEXT; ) { bufcat_id(h, n->string); if (NULL != (n = n->next)) bufcat_id(h, " "); @@ -600,7 +584,7 @@ mdoc_ss_pre(MDOC_ARGS) } else print_otag(h, TAG_H2, 0, NULL); - return(1); + return 1; } static int @@ -614,17 +598,17 @@ mdoc_fl_pre(MDOC_ARGS) /* `Cm' has no leading hyphen. */ if (MDOC_Cm == n->tok) - return(1); + return 1; print_text(h, "\\-"); - if ( ! (n->nchild == 0 && + if (!(n->child == NULL && (n->next == NULL || - n->next->type == MDOC_TEXT || + n->next->type == ROFFT_TEXT || n->next->flags & MDOC_LINE))) h->flags |= HTML_NOSPACE; - return(1); + return 1; } static int @@ -632,15 +616,15 @@ mdoc_nd_pre(MDOC_ARGS) { struct htmlpair tag; - if (MDOC_BODY != n->type) - return(1); + if (n->type != ROFFT_BODY) + return 1; /* XXX: this tag in theory can contain block elements. */ print_text(h, "\\(em"); PAIR_CLASS_INIT(&tag, "desc"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -651,21 +635,18 @@ mdoc_nm_pre(MDOC_ARGS) int len; switch (n->type) { - case MDOC_ELEM: - synopsis_pre(h, n); + case ROFFT_HEAD: + print_otag(h, TAG_TD, 0, NULL); + /* FALLTHROUGH */ + case ROFFT_ELEM: PAIR_CLASS_INIT(&tag, "name"); print_otag(h, TAG_B, 1, &tag); - if (NULL == n->child && meta->name) - print_text(h, meta->name); - return(1); - case MDOC_HEAD: - print_otag(h, TAG_TD, 0, NULL); - if (NULL == n->child && meta->name) + if (n->child == NULL && meta->name != NULL) print_text(h, meta->name); - return(1); - case MDOC_BODY: + return 1; + case ROFFT_BODY: print_otag(h, TAG_TD, 0, NULL); - return(1); + return 1; default: break; } @@ -674,11 +655,11 @@ mdoc_nm_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "synopsis"); print_otag(h, TAG_TABLE, 1, &tag); - for (len = 0, n = n->child; n; n = n->next) - if (MDOC_TEXT == n->type) + for (len = 0, n = n->head->child; n; n = n->next) + if (n->type == ROFFT_TEXT) len += html_strlen(n->string); - if (0 == len && meta->name) + if (len == 0 && meta->name != NULL) len = html_strlen(meta->name); SCALE_HS_INIT(&su, len); @@ -689,7 +670,7 @@ mdoc_nm_pre(MDOC_ARGS) print_otag(h, TAG_COL, 0, NULL); print_otag(h, TAG_TBODY, 0, NULL); print_otag(h, TAG_TR, 0, NULL); - return(1); + return 1; } static int @@ -698,7 +679,7 @@ mdoc_xr_pre(MDOC_ARGS) struct htmlpair tag[2]; if (NULL == n->child) - return(0); + return 0; PAIR_CLASS_INIT(&tag[0], "link-man"); @@ -715,7 +696,7 @@ mdoc_xr_pre(MDOC_ARGS) print_text(h, n->string); if (NULL == (n = n->next)) - return(0); + return 0; h->flags |= HTML_NOSPACE; print_text(h, "("); @@ -723,7 +704,7 @@ mdoc_xr_pre(MDOC_ARGS) print_text(h, n->string); h->flags |= HTML_NOSPACE; print_text(h, ")"); - return(0); + return 0; } static int @@ -732,7 +713,7 @@ mdoc_ns_pre(MDOC_ARGS) if ( ! (MDOC_LINE & n->flags)) h->flags |= HTML_NOSPACE; - return(1); + return 1; } static int @@ -742,7 +723,7 @@ mdoc_ar_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "arg"); print_otag(h, TAG_I, 1, &tag); - return(1); + return 1; } static int @@ -772,7 +753,7 @@ mdoc_xx_pre(MDOC_ARGS) pp = "UNIX"; break; default: - return(1); + return 1; } PAIR_CLASS_INIT(&tag, "unix"); @@ -785,7 +766,7 @@ mdoc_xx_pre(MDOC_ARGS) print_text(h, n->child->string); h->flags = flags; } - return(0); + return 0; } static int @@ -802,7 +783,7 @@ mdoc_bx_pre(MDOC_ARGS) print_text(h, "BSD"); } else { print_text(h, "BSD"); - return(0); + return 0; } if (NULL != (n = n->next)) { @@ -812,7 +793,7 @@ mdoc_bx_pre(MDOC_ARGS) print_text(h, n->string); } - return(0); + return 0; } static int @@ -821,7 +802,7 @@ mdoc_it_pre(MDOC_ARGS) struct roffsu su; enum mdoc_list type; struct htmlpair tag[2]; - const struct mdoc_node *bl; + const struct roff_node *bl; bl = n->parent; while (bl && MDOC_Bl != bl->tok) @@ -836,26 +817,18 @@ mdoc_it_pre(MDOC_ARGS) bufinit(h); - if (MDOC_HEAD == n->type) { + if (n->type == ROFFT_HEAD) { switch (type) { case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_item: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_enum: - return(0); + return 0; case LIST_diag: - /* FALLTHROUGH */ case LIST_hang: - /* FALLTHROUGH */ case LIST_inset: - /* FALLTHROUGH */ case LIST_ohang: - /* FALLTHROUGH */ case LIST_tag: SCALE_VS_INIT(&su, ! bl->norm->Bl.comp); bufcat_su(h, "margin-top", &su); @@ -871,16 +844,12 @@ mdoc_it_pre(MDOC_ARGS) default: break; } - } else if (MDOC_BODY == n->type) { + } else if (n->type == ROFFT_BODY) { switch (type) { case LIST_bullet: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_enum: - /* FALLTHROUGH */ case LIST_item: SCALE_VS_INIT(&su, ! bl->norm->Bl.comp); bufcat_su(h, "margin-top", &su); @@ -888,13 +857,9 @@ mdoc_it_pre(MDOC_ARGS) print_otag(h, TAG_LI, 2, tag); break; case LIST_diag: - /* FALLTHROUGH */ case LIST_hang: - /* FALLTHROUGH */ case LIST_inset: - /* FALLTHROUGH */ case LIST_ohang: - /* FALLTHROUGH */ case LIST_tag: if (NULL == bl->norm->Bl.width) { print_otag(h, TAG_DD, 1, tag); @@ -924,7 +889,7 @@ mdoc_it_pre(MDOC_ARGS) } } - return(1); + return 1; } static int @@ -935,15 +900,15 @@ mdoc_bl_pre(MDOC_ARGS) struct roffsu su; char buf[BUFSIZ]; - if (MDOC_BODY == n->type) { + if (n->type == ROFFT_BODY) { if (LIST_column == n->norm->Bl.type) print_otag(h, TAG_TBODY, 0, NULL); - return(1); + return 1; } - if (MDOC_HEAD == n->type) { + if (n->type == ROFFT_HEAD) { if (LIST_column != n->norm->Bl.type) - return(0); + return 0; /* * For each column, print out the <COL> tag with our @@ -963,7 +928,7 @@ mdoc_bl_pre(MDOC_ARGS) print_otag(h, TAG_COL, 1, tag); } - return(0); + return 0; } SCALE_VS_INIT(&su, 0); @@ -986,11 +951,8 @@ mdoc_bl_pre(MDOC_ARGS) switch (n->norm->Bl.type) { case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_item: print_otag(h, TAG_UL, 2, tag); break; @@ -998,13 +960,9 @@ mdoc_bl_pre(MDOC_ARGS) print_otag(h, TAG_OL, 2, tag); break; case LIST_diag: - /* FALLTHROUGH */ case LIST_hang: - /* FALLTHROUGH */ case LIST_inset: - /* FALLTHROUGH */ case LIST_ohang: - /* FALLTHROUGH */ case LIST_tag: print_otag(h, TAG_DL, 2, tag); break; @@ -1013,18 +971,17 @@ mdoc_bl_pre(MDOC_ARGS) break; default: abort(); - /* NOTREACHED */ } - return(1); + return 1; } static int mdoc_ex_pre(MDOC_ARGS) { - struct tag *t; - struct htmlpair tag; - int nchild; + struct htmlpair tag; + struct tag *t; + struct roff_node *nch; if (n->prev) print_otag(h, TAG_BR, 0, NULL); @@ -1033,30 +990,32 @@ mdoc_ex_pre(MDOC_ARGS) print_text(h, "The"); - nchild = n->nchild; - for (n = n->child; n; n = n->next) { - assert(MDOC_TEXT == n->type); + for (nch = n->child; nch != NULL; nch = nch->next) { + assert(nch->type == ROFFT_TEXT); t = print_otag(h, TAG_B, 1, &tag); - print_text(h, n->string); + print_text(h, nch->string); print_tagq(h, t); - if (nchild > 2 && n->next) { + if (nch->next == NULL) + continue; + + if (nch->prev != NULL || nch->next->next != NULL) { h->flags |= HTML_NOSPACE; print_text(h, ","); } - if (n->next && NULL == n->next->next) + if (nch->next->next == NULL) print_text(h, "and"); } - if (nchild > 1) + if (n->child != NULL && n->child->next != NULL) print_text(h, "utilities exit\\~0"); else print_text(h, "utility exits\\~0"); print_text(h, "on success, and\\~>0 if an error occurs."); - return(0); + return 0; } static int @@ -1066,7 +1025,7 @@ mdoc_em_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "emph"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1075,8 +1034,8 @@ mdoc_d1_pre(MDOC_ARGS) struct htmlpair tag[2]; struct roffsu su; - if (MDOC_BLOCK != n->type) - return(1); + if (n->type != ROFFT_BLOCK) + return 1; SCALE_VS_INIT(&su, 0); bufinit(h); @@ -1095,7 +1054,7 @@ mdoc_d1_pre(MDOC_ARGS) print_otag(h, TAG_CODE, 1, tag); } - return(1); + return 1; } static int @@ -1104,7 +1063,7 @@ mdoc_sx_pre(MDOC_ARGS) struct htmlpair tag[2]; bufinit(h); - bufcat(h, "#x"); + bufcat(h, "#"); for (n = n->child; n; ) { bufcat_id(h, n->string); @@ -1117,7 +1076,7 @@ mdoc_sx_pre(MDOC_ARGS) print_otag(h, TAG_I, 1, tag); print_otag(h, TAG_A, 2, tag); - return(1); + return 1; } static int @@ -1125,16 +1084,16 @@ mdoc_bd_pre(MDOC_ARGS) { struct htmlpair tag[2]; int comp, sv; - struct mdoc_node *nn; + struct roff_node *nn; struct roffsu su; - if (MDOC_HEAD == n->type) - return(0); + if (n->type == ROFFT_HEAD) + return 0; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { comp = n->norm->Bd.comp; for (nn = n; nn && ! comp; nn = nn->parent) { - if (MDOC_BLOCK != nn->type) + if (nn->type != ROFFT_BLOCK) continue; if (MDOC_Ss == nn->tok || MDOC_Sh == nn->tok) comp = 1; @@ -1143,7 +1102,7 @@ mdoc_bd_pre(MDOC_ARGS) } if ( ! comp) print_paragraph(h); - return(1); + return 1; } /* Handle the -offset argument. */ @@ -1166,7 +1125,7 @@ mdoc_bd_pre(MDOC_ARGS) DISP_literal != n->norm->Bd.type) { PAIR_CLASS_INIT(&tag[1], "display"); print_otag(h, TAG_DIV, 2, tag); - return(1); + return 1; } PAIR_CLASS_INIT(&tag[1], "lit display"); @@ -1187,19 +1146,12 @@ mdoc_bd_pre(MDOC_ARGS) */ switch (nn->tok) { case MDOC_Sm: - /* FALLTHROUGH */ case MDOC_br: - /* FALLTHROUGH */ case MDOC_sp: - /* FALLTHROUGH */ case MDOC_Bl: - /* FALLTHROUGH */ case MDOC_D1: - /* FALLTHROUGH */ case MDOC_Dl: - /* FALLTHROUGH */ case MDOC_Lp: - /* FALLTHROUGH */ case MDOC_Pp: continue; default: @@ -1217,7 +1169,7 @@ mdoc_bd_pre(MDOC_ARGS) if (0 == sv) h->flags &= ~HTML_LITERAL; - return(0); + return 0; } static int @@ -1227,7 +1179,7 @@ mdoc_pa_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "file"); print_otag(h, TAG_I, 1, &tag); - return(1); + return 1; } static int @@ -1237,7 +1189,7 @@ mdoc_ad_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "addr"); print_otag(h, TAG_I, 1, &tag); - return(1); + return 1; } static int @@ -1248,12 +1200,12 @@ mdoc_an_pre(MDOC_ARGS) if (n->norm->An.auth == AUTH_split) { h->flags &= ~HTML_NOSPLIT; h->flags |= HTML_SPLIT; - return(0); + return 0; } if (n->norm->An.auth == AUTH_nosplit) { h->flags &= ~HTML_SPLIT; h->flags |= HTML_NOSPLIT; - return(0); + return 0; } if (h->flags & HTML_SPLIT) @@ -1264,7 +1216,7 @@ mdoc_an_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "author"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1275,7 +1227,7 @@ mdoc_cd_pre(MDOC_ARGS) synopsis_pre(h, n); PAIR_CLASS_INIT(&tag, "config"); print_otag(h, TAG_B, 1, &tag); - return(1); + return 1; } static int @@ -1285,7 +1237,7 @@ mdoc_dv_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "define"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1295,7 +1247,7 @@ mdoc_ev_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "env"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1305,20 +1257,20 @@ mdoc_er_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "errno"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int mdoc_fa_pre(MDOC_ARGS) { - const struct mdoc_node *nn; + const struct roff_node *nn; struct htmlpair tag; struct tag *t; PAIR_CLASS_INIT(&tag, "farg"); if (n->parent->tok != MDOC_Fo) { print_otag(h, TAG_I, 1, &tag); - return(1); + return 1; } for (nn = n->child; nn; nn = nn->next) { @@ -1336,7 +1288,7 @@ mdoc_fa_pre(MDOC_ARGS) print_text(h, ","); } - return(0); + return 0; } static int @@ -1351,14 +1303,14 @@ mdoc_fd_pre(MDOC_ARGS) synopsis_pre(h, n); if (NULL == (n = n->child)) - return(0); + return 0; - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); if (strcmp(n->string, "#include")) { PAIR_CLASS_INIT(&tag[0], "macro"); print_otag(h, TAG_B, 1, tag); - return(1); + return 1; } PAIR_CLASS_INIT(&tag[0], "includes"); @@ -1366,7 +1318,7 @@ mdoc_fd_pre(MDOC_ARGS) print_text(h, n->string); if (NULL != (n = n->next)) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); /* * XXX This is broken and not easy to fix. @@ -1400,11 +1352,11 @@ mdoc_fd_pre(MDOC_ARGS) } for ( ; n; n = n->next) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); print_text(h, n->string); } - return(0); + return 0; } static int @@ -1412,17 +1364,17 @@ mdoc_vt_pre(MDOC_ARGS) { struct htmlpair tag; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { synopsis_pre(h, n); - return(1); - } else if (MDOC_ELEM == n->type) { + return 1; + } else if (n->type == ROFFT_ELEM) { synopsis_pre(h, n); - } else if (MDOC_HEAD == n->type) - return(0); + } else if (n->type == ROFFT_HEAD) + return 0; PAIR_CLASS_INIT(&tag, "type"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1433,7 +1385,7 @@ mdoc_ft_pre(MDOC_ARGS) synopsis_pre(h, n); PAIR_CLASS_INIT(&tag, "ftype"); print_otag(h, TAG_I, 1, &tag); - return(1); + return 1; } static int @@ -1523,7 +1475,7 @@ mdoc_fn_pre(MDOC_ARGS) print_text(h, ";"); } - return(0); + return 0; } static int @@ -1540,14 +1492,14 @@ mdoc_sm_pre(MDOC_ARGS) if ( ! (HTML_NONOSPACE & h->flags)) h->flags &= ~HTML_NOSPACE; - return(0); + return 0; } static int mdoc_skip_pre(MDOC_ARGS) { - return(0); + return 0; } static int @@ -1555,7 +1507,7 @@ mdoc_pp_pre(MDOC_ARGS) { print_paragraph(h); - return(0); + return 0; } static int @@ -1584,7 +1536,7 @@ mdoc_sp_pre(MDOC_ARGS) /* So the div isn't empty: */ print_text(h, "\\~"); - return(0); + return 0; } @@ -1594,9 +1546,9 @@ mdoc_lk_pre(MDOC_ARGS) struct htmlpair tag[2]; if (NULL == (n = n->child)) - return(0); + return 0; - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); PAIR_CLASS_INIT(&tag[0], "link-ext"); PAIR_HREF_INIT(&tag[1], n->string); @@ -1609,7 +1561,7 @@ mdoc_lk_pre(MDOC_ARGS) for (n = n->next; n; n = n->next) print_text(h, n->string); - return(0); + return 0; } static int @@ -1621,7 +1573,7 @@ mdoc_mt_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag[0], "link-mail"); for (n = n->child; n; n = n->next) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); bufinit(h); bufcat(h, "mailto:"); @@ -1633,7 +1585,7 @@ mdoc_mt_pre(MDOC_ARGS) print_tagq(h, t); } - return(0); + return 0; } static int @@ -1642,33 +1594,32 @@ mdoc_fo_pre(MDOC_ARGS) struct htmlpair tag; struct tag *t; - if (MDOC_BODY == n->type) { + if (n->type == ROFFT_BODY) { h->flags |= HTML_NOSPACE; print_text(h, "("); h->flags |= HTML_NOSPACE; - return(1); - } else if (MDOC_BLOCK == n->type) { + return 1; + } else if (n->type == ROFFT_BLOCK) { synopsis_pre(h, n); - return(1); + return 1; } - /* XXX: we drop non-initial arguments as per groff. */ + if (n->child == NULL) + return 0; - assert(n->child); assert(n->child->string); - PAIR_CLASS_INIT(&tag, "fname"); t = print_otag(h, TAG_B, 1, &tag); print_text(h, n->child->string); print_tagq(h, t); - return(0); + return 0; } static void mdoc_fo_post(MDOC_ARGS) { - if (MDOC_BODY != n->type) + if (n->type != ROFFT_BODY) return; h->flags |= HTML_NOSPACE; print_text(h, ")"); @@ -1702,7 +1653,7 @@ mdoc_in_pre(MDOC_ARGS) h->flags |= HTML_NOSPACE; if (NULL != (n = n->child)) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); PAIR_CLASS_INIT(&tag[0], "link-includes"); @@ -1724,11 +1675,11 @@ mdoc_in_pre(MDOC_ARGS) print_text(h, ">"); for ( ; n; n = n->next) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); print_text(h, n->string); } - return(0); + return 0; } static int @@ -1738,7 +1689,7 @@ mdoc_ic_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "cmd"); print_otag(h, TAG_B, 1, &tag); - return(1); + return 1; } static int @@ -1746,37 +1697,36 @@ mdoc_rv_pre(MDOC_ARGS) { struct htmlpair tag; struct tag *t; - int nchild; + struct roff_node *nch; if (n->prev) print_otag(h, TAG_BR, 0, NULL); PAIR_CLASS_INIT(&tag, "fname"); - nchild = n->nchild; - if (nchild > 0) { + if (n->child != NULL) { print_text(h, "The"); - for (n = n->child; n; n = n->next) { + for (nch = n->child; nch != NULL; nch = nch->next) { t = print_otag(h, TAG_B, 1, &tag); - print_text(h, n->string); + print_text(h, nch->string); print_tagq(h, t); h->flags |= HTML_NOSPACE; print_text(h, "()"); - if (n->next == NULL) + if (nch->next == NULL) continue; - if (nchild > 2) { + if (nch->prev != NULL || nch->next->next != NULL) { h->flags |= HTML_NOSPACE; print_text(h, ","); } - if (n->next->next == NULL) + if (nch->next->next == NULL) print_text(h, "and"); } - if (nchild > 1) + if (n->child != NULL && n->child->next != NULL) print_text(h, "functions return"); else print_text(h, "function returns"); @@ -1794,7 +1744,7 @@ mdoc_rv_pre(MDOC_ARGS) print_text(h, "errno"); print_tagq(h, t); print_text(h, "is set to indicate the error."); - return(0); + return 0; } static int @@ -1804,7 +1754,7 @@ mdoc_va_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "var"); print_otag(h, TAG_B, 1, &tag); - return(1); + return 1; } static int @@ -1814,7 +1764,7 @@ mdoc_ap_pre(MDOC_ARGS) h->flags |= HTML_NOSPACE; print_text(h, "\\(aq"); h->flags |= HTML_NOSPACE; - return(1); + return 1; } static int @@ -1823,10 +1773,10 @@ mdoc_bf_pre(MDOC_ARGS) struct htmlpair tag[2]; struct roffsu su; - if (MDOC_HEAD == n->type) - return(0); - else if (MDOC_BODY != n->type) - return(1); + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type != ROFFT_BODY) + return 1; if (FONT_Em == n->norm->Bf.font) PAIR_CLASS_INIT(&tag[0], "emph"); @@ -1848,7 +1798,7 @@ mdoc_bf_pre(MDOC_ARGS) bufcat_su(h, "margin-left", &su); PAIR_STYLE_INIT(&tag[1], h); print_otag(h, TAG_DIV, 2, tag); - return(1); + return 1; } static int @@ -1858,7 +1808,7 @@ mdoc_ms_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "symb"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1866,7 +1816,7 @@ mdoc_igndelim_pre(MDOC_ARGS) { h->flags |= HTML_IGNDELIM; - return(1); + return 1; } static void @@ -1882,15 +1832,15 @@ mdoc_rs_pre(MDOC_ARGS) { struct htmlpair tag; - if (MDOC_BLOCK != n->type) - return(1); + if (n->type != ROFFT_BLOCK) + return 1; if (n->prev && SEC_SEE_ALSO == n->sec) print_paragraph(h); PAIR_CLASS_INIT(&tag, "ref"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1900,7 +1850,7 @@ mdoc_no_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "none"); print_otag(h, TAG_CODE, 1, &tag); - return(1); + return 1; } static int @@ -1910,7 +1860,7 @@ mdoc_li_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "lit"); print_otag(h, TAG_CODE, 1, &tag); - return(1); + return 1; } static int @@ -1920,7 +1870,7 @@ mdoc_sy_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "symb"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -1928,7 +1878,7 @@ mdoc_bt_pre(MDOC_ARGS) { print_text(h, "is currently in beta test."); - return(0); + return 0; } static int @@ -1936,7 +1886,7 @@ mdoc_ud_pre(MDOC_ARGS) { print_text(h, "currently under development."); - return(0); + return 0; } static int @@ -1949,7 +1899,7 @@ mdoc_lb_pre(MDOC_ARGS) PAIR_CLASS_INIT(&tag, "lib"); print_otag(h, TAG_SPAN, 1, &tag); - return(1); + return 1; } static int @@ -2011,18 +1961,17 @@ mdoc__x_pre(MDOC_ARGS) break; default: abort(); - /* NOTREACHED */ } if (MDOC__U != n->tok) { print_otag(h, t, 1, tag); - return(1); + return 1; } PAIR_HREF_INIT(&tag[1], n->child->string); print_otag(h, TAG_A, 2, tag); - return(1); + return 1; } static void @@ -2048,27 +1997,26 @@ mdoc_bk_pre(MDOC_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: break; - case MDOC_HEAD: - return(0); - case MDOC_BODY: - if (n->parent->args || 0 == n->prev->nchild) + case ROFFT_HEAD: + return 0; + case ROFFT_BODY: + if (n->parent->args != NULL || n->prev->child == NULL) h->flags |= HTML_PREKEEP; break; default: abort(); - /* NOTREACHED */ } - return(1); + return 1; } static void mdoc_bk_post(MDOC_ARGS) { - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) h->flags &= ~(HTML_KEEP | HTML_PREKEEP); } @@ -2077,28 +2025,24 @@ mdoc_quote_pre(MDOC_ARGS) { struct htmlpair tag; - if (MDOC_BODY != n->type) - return(1); + if (n->type != ROFFT_BODY) + return 1; switch (n->tok) { case MDOC_Ao: - /* FALLTHROUGH */ case MDOC_Aq: - print_text(h, n->nchild == 1 && + print_text(h, n->child != NULL && n->child->next == NULL && n->child->tok == MDOC_Mt ? "<" : "\\(la"); break; case MDOC_Bro: - /* FALLTHROUGH */ case MDOC_Brq: print_text(h, "\\(lC"); break; case MDOC_Bo: - /* FALLTHROUGH */ case MDOC_Bq: print_text(h, "\\(lB"); break; case MDOC_Oo: - /* FALLTHROUGH */ case MDOC_Op: print_text(h, "\\(lB"); h->flags |= HTML_NOSPACE; @@ -2108,20 +2052,16 @@ mdoc_quote_pre(MDOC_ARGS) case MDOC_En: if (NULL == n->norm->Es || NULL == n->norm->Es->child) - return(1); + return 1; print_text(h, n->norm->Es->child->string); break; case MDOC_Do: - /* FALLTHROUGH */ case MDOC_Dq: - /* FALLTHROUGH */ case MDOC_Qo: - /* FALLTHROUGH */ case MDOC_Qq: print_text(h, "\\(lq"); break; case MDOC_Po: - /* FALLTHROUGH */ case MDOC_Pq: print_text(h, "("); break; @@ -2132,46 +2072,39 @@ mdoc_quote_pre(MDOC_ARGS) print_otag(h, TAG_CODE, 1, &tag); break; case MDOC_So: - /* FALLTHROUGH */ case MDOC_Sq: print_text(h, "\\(oq"); break; default: abort(); - /* NOTREACHED */ } h->flags |= HTML_NOSPACE; - return(1); + return 1; } static void mdoc_quote_post(MDOC_ARGS) { - if (n->type != MDOC_BODY && n->type != MDOC_ELEM) + if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) return; h->flags |= HTML_NOSPACE; switch (n->tok) { case MDOC_Ao: - /* FALLTHROUGH */ case MDOC_Aq: - print_text(h, n->nchild == 1 && + print_text(h, n->child != NULL && n->child->next == NULL && n->child->tok == MDOC_Mt ? ">" : "\\(ra"); break; case MDOC_Bro: - /* FALLTHROUGH */ case MDOC_Brq: print_text(h, "\\(rC"); break; case MDOC_Oo: - /* FALLTHROUGH */ case MDOC_Op: - /* FALLTHROUGH */ case MDOC_Bo: - /* FALLTHROUGH */ case MDOC_Bq: print_text(h, "\\(rB"); break; @@ -2184,29 +2117,22 @@ mdoc_quote_post(MDOC_ARGS) print_text(h, n->norm->Es->child->next->string); break; case MDOC_Qo: - /* FALLTHROUGH */ case MDOC_Qq: - /* FALLTHROUGH */ case MDOC_Do: - /* FALLTHROUGH */ case MDOC_Dq: print_text(h, "\\(rq"); break; case MDOC_Po: - /* FALLTHROUGH */ case MDOC_Pq: print_text(h, ")"); break; case MDOC_Ql: - /* FALLTHROUGH */ case MDOC_So: - /* FALLTHROUGH */ case MDOC_Sq: print_text(h, "\\(cq"); break; default: abort(); - /* NOTREACHED */ } } @@ -2214,8 +2140,8 @@ static int mdoc_eo_pre(MDOC_ARGS) { - if (n->type != MDOC_BODY) - return(1); + if (n->type != ROFFT_BODY) + return 1; if (n->end == ENDBODY_NOT && n->parent->head->child == NULL && @@ -2226,7 +2152,7 @@ mdoc_eo_pre(MDOC_ARGS) n->parent->head->child != NULL && (n->child != NULL || (n->parent->tail != NULL && n->parent->tail->child != NULL))) h->flags |= HTML_NOSPACE; - return(1); + return 1; } static void @@ -2234,7 +2160,7 @@ mdoc_eo_post(MDOC_ARGS) { int body, tail; - if (n->type != MDOC_BODY) + if (n->type != ROFFT_BODY) return; if (n->end != ENDBODY_NOT) { diff --git a/usr/src/cmd/mandoc/mdoc_macro.c b/usr/src/cmd/mandoc/mdoc_macro.c index efb48d023f..ca959589ac 100644 --- a/usr/src/cmd/mandoc/mdoc_macro.c +++ b/usr/src/cmd/mandoc/mdoc_macro.c @@ -1,4 +1,4 @@ -/* $Id: mdoc_macro.c,v 1.183 2015/02/12 12:24:33 schwarze Exp $ */ +/* $Id: mdoc_macro.c,v 1.206 2015/10/20 02:01:32 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -26,10 +26,12 @@ #include <string.h> #include <time.h> -#include "mdoc.h" #include "mandoc.h" -#include "libmdoc.h" +#include "roff.h" +#include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" +#include "libmdoc.h" static void blk_full(MACRO_PROT_ARGS); static void blk_exp_close(MACRO_PROT_ARGS); @@ -41,18 +43,19 @@ static void in_line_argn(MACRO_PROT_ARGS); static void in_line(MACRO_PROT_ARGS); static void phrase_ta(MACRO_PROT_ARGS); -static void dword(struct mdoc *, int, int, const char *, - enum mdelim, int); -static void append_delims(struct mdoc *, int, int *, char *); -static enum mdoct lookup(struct mdoc *, enum mdoct, - int, int, const char *); +static void append_delims(struct roff_man *, int, int *, char *); +static void dword(struct roff_man *, int, int, const char *, + enum mdelim, int); +static int find_pending(struct roff_man *, int, int, int, + struct roff_node *); +static int lookup(struct roff_man *, int, int, int, const char *); static int macro_or_word(MACRO_PROT_ARGS, int); -static int parse_rest(struct mdoc *, enum mdoct, - int, int *, char *); -static enum mdoct rew_alt(enum mdoct); -static void rew_elem(struct mdoc *, enum mdoct); -static void rew_last(struct mdoc *, const struct mdoc_node *); -static void rew_pending(struct mdoc *, const struct mdoc_node *); +static int parse_rest(struct roff_man *, int, int, int *, char *); +static int rew_alt(int); +static void rew_elem(struct roff_man *, int); +static void rew_last(struct roff_man *, const struct roff_node *); +static void rew_pending(struct roff_man *, + const struct roff_node *); const struct mdoc_macro __mdoc_macros[MDOC_MAX] = { { in_line_argn, MDOC_CALLABLE | MDOC_PARSED | MDOC_JOIN }, /* Ap */ @@ -207,9 +210,9 @@ const struct mdoc_macro * const mdoc_macros = __mdoc_macros; * are errors. */ void -mdoc_macroend(struct mdoc *mdoc) +mdoc_endparse(struct roff_man *mdoc) { - struct mdoc_node *n; + struct roff_node *n; /* Scan for open explicit scopes. */ @@ -217,7 +220,7 @@ mdoc_macroend(struct mdoc *mdoc) mdoc->last->parent : mdoc->last; for ( ; n; n = n->parent) - if (n->type == MDOC_BLOCK && + if (n->type == ROFFT_BLOCK && mdoc_macros[n->tok].flags & MDOC_EXPLICIT) mandoc_msg(MANDOCERR_BLK_NOEND, mdoc->parse, n->line, n->pos, mdoc_macronames[n->tok]); @@ -225,86 +228,87 @@ mdoc_macroend(struct mdoc *mdoc) /* Rewind to the first. */ rew_last(mdoc, mdoc->first); + mdoc_state_reset(mdoc); } /* * Look up the macro at *p called by "from", - * or as a line macro if from == MDOC_MAX. + * or as a line macro if from == TOKEN_NONE. */ -static enum mdoct -lookup(struct mdoc *mdoc, enum mdoct from, int line, int ppos, const char *p) +static int +lookup(struct roff_man *mdoc, int from, int line, int ppos, const char *p) { - enum mdoct res; + int res; - if (from == MDOC_MAX || mdoc_macros[from].flags & MDOC_PARSED) { + if (mdoc->flags & MDOC_PHRASEQF) { + mdoc->flags &= ~MDOC_PHRASEQF; + return TOKEN_NONE; + } + if (from == TOKEN_NONE || mdoc_macros[from].flags & MDOC_PARSED) { res = mdoc_hash_find(p); - if (res != MDOC_MAX) { + if (res != TOKEN_NONE) { if (mdoc_macros[res].flags & MDOC_CALLABLE) - return(res); + return res; if (res != MDOC_br && res != MDOC_sp && res != MDOC_ll) mandoc_msg(MANDOCERR_MACRO_CALL, mdoc->parse, line, ppos, p); } } - return(MDOC_MAX); + return TOKEN_NONE; } /* * Rewind up to and including a specific node. */ static void -rew_last(struct mdoc *mdoc, const struct mdoc_node *to) +rew_last(struct roff_man *mdoc, const struct roff_node *to) { - struct mdoc_node *n, *np; - assert(to); - mdoc->next = MDOC_NEXT_SIBLING; + if (to->flags & MDOC_VALID) + return; + while (mdoc->last != to) { - /* - * Save the parent here, because we may delete the - * mdoc->last node in the post-validation phase and reset - * it to mdoc->last->parent, causing a step in the closing - * out to be lost. - */ - np = mdoc->last->parent; - mdoc_valid_post(mdoc); - n = mdoc->last; - mdoc->last = np; - assert(mdoc->last); - mdoc->last->last = n; + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= MDOC_VALID | MDOC_ENDED; + mdoc->last = mdoc->last->parent; } - mdoc_valid_post(mdoc); + mdoc_state(mdoc, mdoc->last); + mdoc->last->flags |= MDOC_VALID | MDOC_ENDED; + mdoc->next = ROFF_NEXT_SIBLING; } /* * Rewind up to a specific block, including all blocks that broke it. */ static void -rew_pending(struct mdoc *mdoc, const struct mdoc_node *n) +rew_pending(struct roff_man *mdoc, const struct roff_node *n) { for (;;) { rew_last(mdoc, n); - switch (n->type) { - case MDOC_HEAD: - mdoc_body_alloc(mdoc, n->line, n->pos, n->tok); - return; - case MDOC_BLOCK: - break; - default: - return; - } - - if ( ! (n->flags & MDOC_BROKEN)) - return; + if (mdoc->last == n) { + switch (n->type) { + case ROFFT_HEAD: + roff_body_alloc(mdoc, n->line, n->pos, + n->tok); + return; + case ROFFT_BLOCK: + break; + default: + return; + } + if ( ! (n->flags & MDOC_BROKEN)) + return; + } else + n = mdoc->last; for (;;) { if ((n = n->parent) == NULL) return; - if (n->type == MDOC_BLOCK || - n->type == MDOC_HEAD) { + if (n->type == ROFFT_BLOCK || + n->type == ROFFT_HEAD) { if (n->flags & MDOC_ENDED) break; else @@ -318,67 +322,104 @@ rew_pending(struct mdoc *mdoc, const struct mdoc_node *n) * For a block closing macro, return the corresponding opening one. * Otherwise, return the macro itself. */ -static enum mdoct -rew_alt(enum mdoct tok) +static int +rew_alt(int tok) { switch (tok) { case MDOC_Ac: - return(MDOC_Ao); + return MDOC_Ao; case MDOC_Bc: - return(MDOC_Bo); + return MDOC_Bo; case MDOC_Brc: - return(MDOC_Bro); + return MDOC_Bro; case MDOC_Dc: - return(MDOC_Do); + return MDOC_Do; case MDOC_Ec: - return(MDOC_Eo); + return MDOC_Eo; case MDOC_Ed: - return(MDOC_Bd); + return MDOC_Bd; case MDOC_Ef: - return(MDOC_Bf); + return MDOC_Bf; case MDOC_Ek: - return(MDOC_Bk); + return MDOC_Bk; case MDOC_El: - return(MDOC_Bl); + return MDOC_Bl; case MDOC_Fc: - return(MDOC_Fo); + return MDOC_Fo; case MDOC_Oc: - return(MDOC_Oo); + return MDOC_Oo; case MDOC_Pc: - return(MDOC_Po); + return MDOC_Po; case MDOC_Qc: - return(MDOC_Qo); + return MDOC_Qo; case MDOC_Re: - return(MDOC_Rs); + return MDOC_Rs; case MDOC_Sc: - return(MDOC_So); + return MDOC_So; case MDOC_Xc: - return(MDOC_Xo); + return MDOC_Xo; default: - return(tok); + return tok; } - /* NOTREACHED */ } static void -rew_elem(struct mdoc *mdoc, enum mdoct tok) +rew_elem(struct roff_man *mdoc, int tok) { - struct mdoc_node *n; + struct roff_node *n; n = mdoc->last; - if (MDOC_ELEM != n->type) + if (n->type != ROFFT_ELEM) n = n->parent; - assert(MDOC_ELEM == n->type); + assert(n->type == ROFFT_ELEM); assert(tok == n->tok); rew_last(mdoc, n); } /* + * If there is an open sub-block of the target requiring + * explicit close-out, postpone closing out the target until + * the rew_pending() call closing out the sub-block. + */ +static int +find_pending(struct roff_man *mdoc, int tok, int line, int ppos, + struct roff_node *target) +{ + struct roff_node *n; + int irc; + + irc = 0; + for (n = mdoc->last; n != NULL && n != target; n = n->parent) { + if (n->flags & MDOC_ENDED) { + if ( ! (n->flags & MDOC_VALID)) + n->flags |= MDOC_BROKEN; + continue; + } + if (n->type == ROFFT_BLOCK && + mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { + irc = 1; + n->flags = MDOC_BROKEN; + if (target->type == ROFFT_HEAD) + target->flags = MDOC_ENDED; + else if ( ! (target->flags & MDOC_ENDED)) { + mandoc_vmsg(MANDOCERR_BLK_NEST, + mdoc->parse, line, ppos, + "%s breaks %s", mdoc_macronames[tok], + mdoc_macronames[n->tok]); + mdoc_endbody_alloc(mdoc, line, ppos, + tok, target, ENDBODY_NOSPACE); + } + } + } + return irc; +} + +/* * Allocate a word and check whether it's punctuation or not. * Punctuation consists of those tokens found in mdoc_isdelim(). */ static void -dword(struct mdoc *mdoc, int line, int col, const char *p, +dword(struct roff_man *mdoc, int line, int col, const char *p, enum mdelim d, int may_append) { @@ -387,13 +428,13 @@ dword(struct mdoc *mdoc, int line, int col, const char *p, if (may_append && ! (mdoc->flags & (MDOC_SYNOPSIS | MDOC_KEEP | MDOC_SMOFF)) && - d == DELIM_NONE && mdoc->last->type == MDOC_TEXT && + d == DELIM_NONE && mdoc->last->type == ROFFT_TEXT && mdoc_isdelim(mdoc->last->string) == DELIM_NONE) { - mdoc_word_append(mdoc, p); + roff_word_append(mdoc, p); return; } - mdoc_word_alloc(mdoc, line, col, p); + roff_word_alloc(mdoc, line, col, p); /* * If the word consists of a bare delimiter, @@ -412,7 +453,7 @@ dword(struct mdoc *mdoc, int line, int col, const char *p, } static void -append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) +append_delims(struct roff_man *mdoc, int line, int *pos, char *buf) { char *p; int la; @@ -422,7 +463,8 @@ append_delims(struct mdoc *mdoc, int line, int *pos, char *buf) for (;;) { la = *pos; - if (mdoc_args(mdoc, line, pos, buf, MDOC_MAX, &p) == ARGS_EOLN) + if (mdoc_args(mdoc, line, pos, buf, TOKEN_NONE, &p) == + ARGS_EOLN) break; dword(mdoc, line, la, p, DELIM_MAX, 1); @@ -452,26 +494,26 @@ static int macro_or_word(MACRO_PROT_ARGS, int parsed) { char *p; - enum mdoct ntok; + int ntok; p = buf + ppos; - ntok = MDOC_MAX; + ntok = TOKEN_NONE; if (*p == '"') p++; else if (parsed && ! (mdoc->flags & MDOC_PHRASELIT)) ntok = lookup(mdoc, tok, line, ppos, p); - if (ntok == MDOC_MAX) { - dword(mdoc, line, ppos, p, DELIM_MAX, tok == MDOC_MAX || + if (ntok == TOKEN_NONE) { + dword(mdoc, line, ppos, p, DELIM_MAX, tok == TOKEN_NONE || mdoc_macros[tok].flags & MDOC_JOIN); - return(0); + return 0; } else { if (mdoc_macros[tok].fp == in_line_eoln) rew_elem(mdoc, tok); mdoc_macro(mdoc, ntok, line, ppos, pos, buf); - if (tok == MDOC_MAX) + if (tok == TOKEN_NONE) append_delims(mdoc, line, pos, buf); - return(1); + return 1; } } @@ -481,15 +523,16 @@ macro_or_word(MACRO_PROT_ARGS, int parsed) static void blk_exp_close(MACRO_PROT_ARGS) { - struct mdoc_node *body; /* Our own body. */ - struct mdoc_node *endbody; /* Our own end marker. */ - struct mdoc_node *itblk; /* An It block starting later. */ - struct mdoc_node *later; /* A sub-block starting later. */ - struct mdoc_node *n; /* Search back to our block. */ - - int j, lastarg, maxargs, nl; + struct roff_node *body; /* Our own body. */ + struct roff_node *endbody; /* Our own end marker. */ + struct roff_node *itblk; /* An It block starting later. */ + struct roff_node *later; /* A sub-block starting later. */ + struct roff_node *n; /* Search back to our block. */ + struct roff_node *target; /* For find_pending(). */ + + int j, lastarg, maxargs, nl, pending; enum margserr ac; - enum mdoct atok, ntok; + int atok, ntok; char *p; nl = MDOC_NEWLINE & mdoc->flags; @@ -522,13 +565,13 @@ blk_exp_close(MACRO_PROT_ARGS) /* Remember the start of our own body. */ - if (n->type == MDOC_BODY && atok == n->tok) { + if (n->type == ROFFT_BODY && atok == n->tok) { if (n->end == ENDBODY_NOT) body = n; continue; } - if (n->type != MDOC_BLOCK || n->tok == MDOC_Nm) + if (n->type != ROFFT_BLOCK || n->tok == MDOC_Nm) continue; if (n->tok == MDOC_It) { @@ -575,7 +618,7 @@ blk_exp_close(MACRO_PROT_ARGS) */ if (maxargs) - mdoc->next = MDOC_NEXT_CHILD; + mdoc->next = ROFF_NEXT_CHILD; break; } @@ -596,12 +639,14 @@ blk_exp_close(MACRO_PROT_ARGS) if (body == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, mdoc->parse, line, ppos, mdoc_macronames[tok]); + if (later != NULL) + later->flags &= ~MDOC_BROKEN; if (maxargs && endbody == NULL) { /* * Stray .Ec without previous .Eo: * Break the output line, keep the arguments. */ - mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); + roff_elem_alloc(mdoc, line, ppos, MDOC_br); rew_elem(mdoc, MDOC_br); } } else if (endbody == NULL) { @@ -623,38 +668,47 @@ blk_exp_close(MACRO_PROT_ARGS) if (endbody != NULL) n = endbody; + + ntok = TOKEN_NONE; for (j = 0; ; j++) { lastarg = *pos; - if (j == maxargs && n != NULL) { - rew_pending(mdoc, n); - n = NULL; - } + if (j == maxargs && n != NULL) + rew_last(mdoc, n); ac = mdoc_args(mdoc, line, pos, buf, tok, &p); if (ac == ARGS_PUNCT || ac == ARGS_EOLN) break; - ntok = ac == ARGS_QWORD ? MDOC_MAX : + ntok = ac == ARGS_QWORD ? TOKEN_NONE : lookup(mdoc, tok, line, lastarg, p); - if (ntok == MDOC_MAX) { + if (ntok == TOKEN_NONE) { dword(mdoc, line, lastarg, p, DELIM_MAX, MDOC_JOIN & mdoc_macros[tok].flags); continue; } - if (n != NULL) { - rew_pending(mdoc, n); - n = NULL; - } + if (n != NULL) + rew_last(mdoc, n); mdoc->flags &= ~MDOC_NEWLINE; mdoc_macro(mdoc, ntok, line, lastarg, pos, buf); break; } - if (n != NULL) - rew_pending(mdoc, n); + if (n != NULL) { + if (ntok != TOKEN_NONE && n->flags & MDOC_BROKEN) { + target = n; + do + target = target->parent; + while ( ! (target->flags & MDOC_ENDED)); + pending = find_pending(mdoc, ntok, line, ppos, + target); + } else + pending = 0; + if ( ! pending) + rew_pending(mdoc, n); + } if (nl) append_delims(mdoc, line, pos, buf); } @@ -663,7 +717,7 @@ static void in_line(MACRO_PROT_ARGS) { int la, scope, cnt, firstarg, mayopen, nc, nl; - enum mdoct ntok; + int ntok; enum margserr ac; enum mdelim d; struct mdoc_arg *arg; @@ -678,15 +732,10 @@ in_line(MACRO_PROT_ARGS) switch (tok) { case MDOC_An: - /* FALLTHROUGH */ case MDOC_Ar: - /* FALLTHROUGH */ case MDOC_Fl: - /* FALLTHROUGH */ case MDOC_Mt: - /* FALLTHROUGH */ case MDOC_Nm: - /* FALLTHROUGH */ case MDOC_Pa: nc = 1; break; @@ -730,7 +779,7 @@ in_line(MACRO_PROT_ARGS) } ntok = (ac == ARGS_QWORD || (tok == MDOC_Fn && !cnt)) ? - MDOC_MAX : lookup(mdoc, tok, line, la, p); + TOKEN_NONE : lookup(mdoc, tok, line, la, p); /* * In this case, we've located a submacro and must @@ -739,7 +788,7 @@ in_line(MACRO_PROT_ARGS) * or raise a warning. */ - if (ntok != MDOC_MAX) { + if (ntok != TOKEN_NONE) { if (scope) rew_elem(mdoc, tok); if (nc && ! cnt) { @@ -847,10 +896,10 @@ blk_full(MACRO_PROT_ARGS) { int la, nl, parsed; struct mdoc_arg *arg; - struct mdoc_node *blk; /* Our own or a broken block. */ - struct mdoc_node *head; /* Our own head. */ - struct mdoc_node *body; /* Our own body. */ - struct mdoc_node *n; + struct roff_node *blk; /* Our own or a broken block. */ + struct roff_node *head; /* Our own head. */ + struct roff_node *body; /* Our own body. */ + struct roff_node *n; enum margserr ac, lac; char *p; @@ -873,7 +922,7 @@ blk_full(MACRO_PROT_ARGS) n->flags |= MDOC_BROKEN; continue; } - if (n->type != MDOC_BLOCK) + if (n->type != ROFFT_BLOCK) continue; if (tok == MDOC_It && n->tok == MDOC_Bl) { @@ -890,7 +939,6 @@ blk_full(MACRO_PROT_ARGS) if (mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { switch (tok) { case MDOC_Sh: - /* FALLTHROUGH */ case MDOC_Ss: mandoc_vmsg(MANDOCERR_BLK_BROKEN, mdoc->parse, line, ppos, @@ -938,7 +986,7 @@ blk_full(MACRO_PROT_ARGS) if (tok == MDOC_It && (n == NULL || n->tok != MDOC_Bl)) { mandoc_vmsg(MANDOCERR_IT_STRAY, mdoc->parse, line, ppos, "It %s", buf + *pos); - mdoc_elem_alloc(mdoc, line, ppos, MDOC_br, NULL); + roff_elem_alloc(mdoc, line, ppos, MDOC_br); rew_elem(mdoc, MDOC_br); return; } @@ -972,34 +1020,47 @@ blk_full(MACRO_PROT_ARGS) */ if (tok == MDOC_Nd) { - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); rew_last(mdoc, head); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); } if (tok == MDOC_Bk) mdoc->flags |= MDOC_KEEP; - ac = ARGS_PEND; + ac = ARGS_EOLN; for (;;) { + + /* + * If we are right after a tab character, + * do not parse the first word for macros. + */ + + if (mdoc->flags & MDOC_PHRASEQN) { + mdoc->flags &= ~MDOC_PHRASEQN; + mdoc->flags |= MDOC_PHRASEQF; + } + la = *pos; lac = ac; ac = mdoc_args(mdoc, line, pos, buf, tok, &p); if (ac == ARGS_EOLN) { - if (lac != ARGS_PPHRASE && lac != ARGS_PHRASE) + if (lac != ARGS_PHRASE || + ! (mdoc->flags & MDOC_PHRASEQF)) break; + /* - * This is necessary: if the last token on a - * line is a `Ta' or tab, then we'll get - * ARGS_EOLN, so we must be smart enough to - * reopen our scope if the last parse was a - * phrase or partial phrase. + * This line ends in a tab; start the next + * column now, with a leading blank. */ + if (body != NULL) rew_last(mdoc, body); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); + roff_word_alloc(mdoc, line, ppos, "\\&"); break; } + if (tok == MDOC_Bd || tok == MDOC_Bk) { mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, line, la, "%s ... %s", @@ -1016,13 +1077,11 @@ blk_full(MACRO_PROT_ARGS) /* * Emit leading punctuation (i.e., punctuation before - * the MDOC_HEAD) for non-phrase types. + * the ROFFT_HEAD) for non-phrase types. */ if (head == NULL && - ac != ARGS_PEND && ac != ARGS_PHRASE && - ac != ARGS_PPHRASE && ac != ARGS_QWORD && mdoc_isdelim(p) == DELIM_OPEN) { dword(mdoc, line, la, p, DELIM_OPEN, 0); @@ -1032,11 +1091,9 @@ blk_full(MACRO_PROT_ARGS) /* Open a head if one hasn't been opened. */ if (head == NULL) - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); - if (ac == ARGS_PHRASE || - ac == ARGS_PEND || - ac == ARGS_PPHRASE) { + if (ac == ARGS_PHRASE) { /* * If we haven't opened a body yet, rewind the @@ -1044,20 +1101,18 @@ blk_full(MACRO_PROT_ARGS) */ rew_last(mdoc, body == NULL ? head : body); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); - /* - * Process phrases: set whether we're in a - * partial-phrase (this effects line handling) - * then call down into the phrase parser. - */ + /* Process to the tab or to the end of the line. */ - if (ac == ARGS_PPHRASE) - mdoc->flags |= MDOC_PPHRASE; - if (ac == ARGS_PEND && lac == ARGS_PPHRASE) - mdoc->flags |= MDOC_PPHRASE; - parse_rest(mdoc, MDOC_MAX, line, &la, buf); - mdoc->flags &= ~MDOC_PPHRASE; + mdoc->flags |= MDOC_PHRASE; + parse_rest(mdoc, TOKEN_NONE, line, &la, buf); + mdoc->flags &= ~MDOC_PHRASE; + + /* There may have been `Ta' macros. */ + + while (body->next != NULL) + body = body->next; continue; } @@ -1068,37 +1123,18 @@ blk_full(MACRO_PROT_ARGS) if (blk->flags & MDOC_VALID) return; if (head == NULL) - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); if (nl && tok != MDOC_Bd && tok != MDOC_Bl && tok != MDOC_Rs) append_delims(mdoc, line, pos, buf); if (body != NULL) goto out; - - /* - * If there is an open (i.e., unvalidated) sub-block requiring - * explicit close-out, postpone switching the current block from - * head to body until the rew_pending() call closing out that - * sub-block. - */ - for (n = mdoc->last; n && n != head; n = n->parent) { - if (n->flags & MDOC_ENDED) { - if ( ! (n->flags & MDOC_VALID)) - n->flags |= MDOC_BROKEN; - continue; - } - if (n->type == MDOC_BLOCK && - mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { - n->flags = MDOC_BROKEN; - head->flags = MDOC_ENDED; - } - } - if (head->flags & MDOC_ENDED) + if (find_pending(mdoc, tok, line, ppos, head)) return; /* Close out scopes to remain in a consistent state. */ rew_last(mdoc, head); - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); out: if (mdoc->flags & MDOC_FREECOL) { rew_last(mdoc, body); @@ -1113,9 +1149,9 @@ blk_part_imp(MACRO_PROT_ARGS) int la, nl; enum margserr ac; char *p; - struct mdoc_node *blk; /* saved block context */ - struct mdoc_node *body; /* saved body context */ - struct mdoc_node *n; + struct roff_node *blk; /* saved block context */ + struct roff_node *body; /* saved body context */ + struct roff_node *n; nl = MDOC_NEWLINE & mdoc->flags; @@ -1129,7 +1165,7 @@ blk_part_imp(MACRO_PROT_ARGS) */ blk = mdoc_block_alloc(mdoc, line, ppos, tok, NULL); - rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok)); + rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok)); /* * Open the body scope "on-demand", that is, after we've @@ -1150,42 +1186,15 @@ blk_part_imp(MACRO_PROT_ARGS) } if (body == NULL) - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) break; } if (body == NULL) - body = mdoc_body_alloc(mdoc, line, ppos, tok); + body = roff_body_alloc(mdoc, line, ppos, tok); - /* - * If there is an open sub-block requiring explicit close-out, - * postpone closing out the current block until the - * rew_pending() call closing out the sub-block. - */ - - for (n = mdoc->last; n && n != body && n != blk->parent; - n = n->parent) { - if (n->flags & MDOC_ENDED) { - if ( ! (n->flags & MDOC_VALID)) - n->flags |= MDOC_BROKEN; - continue; - } - if (n->type == MDOC_BLOCK && - mdoc_macros[n->tok].flags & MDOC_EXPLICIT) { - n->flags |= MDOC_BROKEN; - if ( ! (body->flags & MDOC_ENDED)) { - mandoc_vmsg(MANDOCERR_BLK_NEST, - mdoc->parse, line, ppos, - "%s breaks %s", mdoc_macronames[tok], - mdoc_macronames[n->tok]); - mdoc_endbody_alloc(mdoc, line, ppos, - tok, body, ENDBODY_NOSPACE); - } - } - } - assert(n == body); - if (body->flags & MDOC_ENDED) + if (find_pending(mdoc, tok, line, ppos, body)) return; rew_last(mdoc, body); @@ -1206,7 +1215,7 @@ blk_part_exp(MACRO_PROT_ARGS) { int la, nl; enum margserr ac; - struct mdoc_node *head; /* keep track of head */ + struct roff_node *head; /* keep track of head */ char *p; nl = MDOC_NEWLINE & mdoc->flags; @@ -1217,7 +1226,7 @@ blk_part_exp(MACRO_PROT_ARGS) * case of `Eo'); and a body that may be empty. */ - mdoc_block_alloc(mdoc, line, ppos, tok, NULL); + roff_block_alloc(mdoc, line, ppos, tok); head = NULL; for (;;) { la = *pos; @@ -1234,11 +1243,11 @@ blk_part_exp(MACRO_PROT_ARGS) } if (head == NULL) { - head = mdoc_head_alloc(mdoc, line, ppos, tok); + head = roff_head_alloc(mdoc, line, ppos, tok); if (tok == MDOC_Eo) /* Not parsed. */ dword(mdoc, line, la, p, DELIM_MAX, 0); rew_last(mdoc, head); - mdoc_body_alloc(mdoc, line, ppos, tok); + roff_body_alloc(mdoc, line, ppos, tok); if (tok == MDOC_Eo) continue; } @@ -1250,8 +1259,8 @@ blk_part_exp(MACRO_PROT_ARGS) /* Clean-up to leave in a consistent state. */ if (head == NULL) { - rew_last(mdoc, mdoc_head_alloc(mdoc, line, ppos, tok)); - mdoc_body_alloc(mdoc, line, ppos, tok); + rew_last(mdoc, roff_head_alloc(mdoc, line, ppos, tok)); + roff_body_alloc(mdoc, line, ppos, tok); } if (nl) append_delims(mdoc, line, pos, buf); @@ -1263,7 +1272,7 @@ in_line_argn(MACRO_PROT_ARGS) struct mdoc_arg *arg; char *p; enum margserr ac; - enum mdoct ntok; + int ntok; int state; /* arg#; -1: not yet open; -2: closed */ int la, maxargs, nl; @@ -1279,16 +1288,12 @@ in_line_argn(MACRO_PROT_ARGS) switch (tok) { case MDOC_Ap: - /* FALLTHROUGH */ case MDOC_Ns: - /* FALLTHROUGH */ case MDOC_Ux: maxargs = 0; break; case MDOC_Bx: - /* FALLTHROUGH */ case MDOC_Es: - /* FALLTHROUGH */ case MDOC_Xr: maxargs = 2; break; @@ -1332,9 +1337,9 @@ in_line_argn(MACRO_PROT_ARGS) } ntok = (ac == ARGS_QWORD || (tok == MDOC_Pf && state == 0)) ? - MDOC_MAX : lookup(mdoc, tok, line, la, p); + TOKEN_NONE : lookup(mdoc, tok, line, la, p); - if (ntok != MDOC_MAX) { + if (ntok != TOKEN_NONE) { if (state >= 0) { rew_elem(mdoc, tok); state = -2; @@ -1377,16 +1382,16 @@ in_line_argn(MACRO_PROT_ARGS) static void in_line_eoln(MACRO_PROT_ARGS) { - struct mdoc_node *n; + struct roff_node *n; struct mdoc_arg *arg; if ((tok == MDOC_Pp || tok == MDOC_Lp) && ! (mdoc->flags & MDOC_SYNOPSIS)) { n = mdoc->last; - if (mdoc->next == MDOC_NEXT_SIBLING) + if (mdoc->next == ROFF_NEXT_SIBLING) n = n->parent; if (n->tok == MDOC_Nm) - rew_last(mdoc, mdoc->last->parent); + rew_last(mdoc, n->parent); } if (buf[*pos] == '\0' && @@ -1409,16 +1414,16 @@ in_line_eoln(MACRO_PROT_ARGS) * or until the next macro, call that macro, and return 1. */ static int -parse_rest(struct mdoc *mdoc, enum mdoct tok, int line, int *pos, char *buf) +parse_rest(struct roff_man *mdoc, int tok, int line, int *pos, char *buf) { int la; for (;;) { la = *pos; if (mdoc_args(mdoc, line, pos, buf, tok, NULL) == ARGS_EOLN) - return(0); + return 0; if (macro_or_word(mdoc, tok, line, la, pos, buf, 1)) - return(1); + return 1; } } @@ -1444,7 +1449,7 @@ ctx_synopsis(MACRO_PROT_ARGS) static void phrase_ta(MACRO_PROT_ARGS) { - struct mdoc_node *body, *n; + struct roff_node *body, *n; /* Make sure we are in a column list or ignore this macro. */ @@ -1452,7 +1457,7 @@ phrase_ta(MACRO_PROT_ARGS) for (n = mdoc->last; n != NULL; n = n->parent) { if (n->flags & MDOC_ENDED) continue; - if (n->tok == MDOC_It && n->type == MDOC_BODY) + if (n->tok == MDOC_It && n->type == ROFFT_BODY) body = n; if (n->tok == MDOC_Bl) break; @@ -1467,6 +1472,6 @@ phrase_ta(MACRO_PROT_ARGS) /* Advance to the next column. */ rew_last(mdoc, body); - mdoc_body_alloc(mdoc, line, ppos, MDOC_It); - parse_rest(mdoc, MDOC_MAX, line, pos, buf); + roff_body_alloc(mdoc, line, ppos, MDOC_It); + parse_rest(mdoc, TOKEN_NONE, line, pos, buf); } diff --git a/usr/src/cmd/mandoc/mdoc_man.c b/usr/src/cmd/mandoc/mdoc_man.c index 9c086a576c..ab24531349 100644 --- a/usr/src/cmd/mandoc/mdoc_man.c +++ b/usr/src/cmd/mandoc/mdoc_man.c @@ -1,6 +1,6 @@ -/* $Id: mdoc_man.c,v 1.88 2015/02/17 20:37:17 schwarze Exp $ */ +/* $Id: mdoc_man.c,v 1.96 2016/01/08 17:48:09 schwarze Exp $ */ /* - * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011-2016 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,14 +22,15 @@ #include <stdio.h> #include <string.h> -#include "mandoc.h" #include "mandoc_aux.h" -#include "out.h" -#include "man.h" +#include "mandoc.h" +#include "roff.h" #include "mdoc.h" +#include "man.h" +#include "out.h" #include "main.h" -#define DECL_ARGS const struct mdoc_meta *meta, struct mdoc_node *n +#define DECL_ARGS const struct roff_meta *meta, struct roff_node *n struct manact { int (*cond)(DECL_ARGS); /* DON'T run actions */ @@ -107,7 +108,7 @@ static int pre_sm(DECL_ARGS); static int pre_sp(DECL_ARGS); static int pre_sect(DECL_ARGS); static int pre_sy(DECL_ARGS); -static void pre_syn(const struct mdoc_node *); +static void pre_syn(const struct roff_node *); static int pre_vt(DECL_ARGS); static int pre_ux(DECL_ARGS); static int pre_xr(DECL_ARGS); @@ -116,7 +117,7 @@ static void print_line(const char *, int); static void print_block(const char *, int); static void print_offs(const char *, int); static void print_width(const struct mdoc_bl *, - const struct mdoc_node *); + const struct roff_node *); static void print_count(int *); static void print_node(DECL_ARGS); @@ -467,7 +468,7 @@ print_offs(const char *v, int keywords) * Set up the indentation for a list item; used from pre_it(). */ static void -print_width(const struct mdoc_bl *bl, const struct mdoc_node *child) +print_width(const struct mdoc_bl *bl, const struct roff_node *child) { char buf[24]; struct roffsu su; @@ -492,7 +493,7 @@ print_width(const struct mdoc_bl *bl, const struct mdoc_node *child) /* XXX Rough estimation, might have multiple parts. */ if (bl->type == LIST_enum) chsz = (bl->count > 8) + 1; - else if (child != NULL && child->type == MDOC_TEXT) + else if (child != NULL && child->type == ROFFT_TEXT) chsz = strlen(child->string); else chsz = 0; @@ -531,7 +532,7 @@ print_count(int *count) } void -man_man(void *arg, const struct man *man) +man_man(void *arg, const struct roff_man *man) { /* @@ -544,18 +545,14 @@ man_man(void *arg, const struct man *man) } void -man_mdoc(void *arg, const struct mdoc *mdoc) +man_mdoc(void *arg, const struct roff_man *mdoc) { - const struct mdoc_meta *meta; - struct mdoc_node *n; - - meta = mdoc_meta(mdoc); - n = mdoc_node(mdoc)->child; + struct roff_node *n; printf(".TH \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"\n", - meta->title, - (meta->msec == NULL ? "" : meta->msec), - meta->date, meta->os, meta->vol); + mdoc->meta.title, + (mdoc->meta.msec == NULL ? "" : mdoc->meta.msec), + mdoc->meta.date, mdoc->meta.os, mdoc->meta.vol); /* Disable hyphenation and if nroff, disable justification. */ printf(".nh\n.if n .ad l"); @@ -566,10 +563,8 @@ man_mdoc(void *arg, const struct mdoc *mdoc) fontqueue.head = fontqueue.tail = mandoc_malloc(8); *fontqueue.tail = 'R'; } - while (n != NULL) { - print_node(meta, n); - n = n->next; - } + for (n = mdoc->first->child; n != NULL; n = n->next) + print_node(&mdoc->meta, n); putchar('\n'); } @@ -577,7 +572,7 @@ static void print_node(DECL_ARGS) { const struct manact *act; - struct mdoc_node *sub; + struct roff_node *sub; int cond, do_sub; /* @@ -592,7 +587,7 @@ print_node(DECL_ARGS) do_sub = 1; n->flags &= ~MDOC_ENDED; - if (MDOC_TEXT == n->type) { + if (n->type == ROFFT_TEXT) { /* * Make sure that we don't happen to start with a * control character at the start of a line. @@ -615,7 +610,8 @@ print_node(DECL_ARGS) */ act = manacts + n->tok; cond = act->cond == NULL || (*act->cond)(meta, n); - if (cond && act->pre && (n->end == ENDBODY_NOT || n->nchild)) + if (cond && act->pre != NULL && + (n->end == ENDBODY_NOT || n->child != NULL)) do_sub = (*act->pre)(meta, n); } @@ -648,14 +644,14 @@ static int cond_head(DECL_ARGS) { - return(MDOC_HEAD == n->type); + return n->type == ROFFT_HEAD; } static int cond_body(DECL_ARGS) { - return(MDOC_BODY == n->type); + return n->type == ROFFT_BODY; } static int @@ -665,10 +661,10 @@ pre_enc(DECL_ARGS) prefix = manacts[n->tok].prefix; if (NULL == prefix) - return(1); + return 1; print_word(prefix); outflags &= ~MMAN_spc; - return(1); + return 1; } static void @@ -686,37 +682,36 @@ post_enc(DECL_ARGS) static int pre_ex(DECL_ARGS) { - int nchild; + struct roff_node *nch; outflags |= MMAN_br | MMAN_nl; print_word("The"); - nchild = n->nchild; - for (n = n->child; n; n = n->next) { + for (nch = n->child; nch != NULL; nch = nch->next) { font_push('B'); - print_word(n->string); + print_word(nch->string); font_pop(); - if (n->next == NULL) + if (nch->next == NULL) continue; - if (nchild > 2) { + if (nch->prev != NULL || nch->next->next != NULL) { outflags &= ~MMAN_spc; print_word(","); } - if (n->next->next == NULL) + if (nch->next->next == NULL) print_word("and"); } - if (nchild > 1) + if (n->child != NULL && n->child->next != NULL) print_word("utilities exit\\~0"); else print_word("utility exits\\~0"); print_word("on success, and\\~>0 if an error occurs."); outflags |= MMAN_nl; - return(0); + return 0; } static void @@ -754,7 +749,7 @@ pre__t(DECL_ARGS) outflags &= ~MMAN_spc; } else font_push('I'); - return(1); + return 1; } static void @@ -778,14 +773,14 @@ static int pre_sect(DECL_ARGS) { - if (MDOC_HEAD == n->type) { + if (n->type == ROFFT_HEAD) { outflags |= MMAN_sp; print_block(manacts[n->tok].prefix, 0); print_word(""); putchar('\"'); outflags &= ~MMAN_spc; } - return(1); + return 1; } /* @@ -795,7 +790,7 @@ static void post_sect(DECL_ARGS) { - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) return; outflags &= ~MMAN_spc; print_word(""); @@ -807,7 +802,7 @@ post_sect(DECL_ARGS) /* See mdoc_term.c, synopsis_pre() for comments. */ static void -pre_syn(const struct mdoc_node *n) +pre_syn(const struct roff_node *n) { if (NULL == n->prev || ! (MDOC_SYNPRETTY & n->flags)) @@ -823,13 +818,9 @@ pre_syn(const struct mdoc_node *n) switch (n->prev->tok) { case MDOC_Fd: - /* FALLTHROUGH */ case MDOC_Fn: - /* FALLTHROUGH */ case MDOC_Fo: - /* FALLTHROUGH */ case MDOC_In: - /* FALLTHROUGH */ case MDOC_Vt: outflags |= MMAN_sp; break; @@ -853,18 +844,18 @@ pre_an(DECL_ARGS) case AUTH_split: outflags &= ~MMAN_An_nosplit; outflags |= MMAN_An_split; - return(0); + return 0; case AUTH_nosplit: outflags &= ~MMAN_An_split; outflags |= MMAN_An_nosplit; - return(0); + return 0; default: if (MMAN_An_split & outflags) outflags |= MMAN_br; else if (SEC_AUTHORS == n->sec && ! (MMAN_An_nosplit & outflags)) outflags |= MMAN_An_split; - return(1); + return 1; } } @@ -875,17 +866,17 @@ pre_ap(DECL_ARGS) outflags &= ~MMAN_spc; print_word("'"); outflags &= ~MMAN_spc; - return(0); + return 0; } static int pre_aq(DECL_ARGS) { - print_word(n->nchild == 1 && + print_word(n->child != NULL && n->child->next == NULL && n->child->tok == MDOC_Mt ? "<" : "\\(la"); outflags &= ~MMAN_spc; - return(1); + return 1; } static void @@ -893,7 +884,7 @@ post_aq(DECL_ARGS) { outflags &= ~(MMAN_spc | MMAN_nl); - print_word(n->nchild == 1 && + print_word(n->child != NULL && n->child->next == NULL && n->child->tok == MDOC_Mt ? ">" : "\\(ra"); } @@ -909,7 +900,7 @@ pre_bd(DECL_ARGS) if (0 == n->norm->Bd.comp && NULL != n->parent->prev) outflags |= MMAN_sp; print_offs(n->norm->Bd.offs, 1); - return(1); + return 1; } static void @@ -932,12 +923,12 @@ pre_bf(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: - return(1); - case MDOC_BODY: + case ROFFT_BLOCK: + return 1; + case ROFFT_BODY: break; default: - return(0); + return 0; } switch (n->norm->Bf.font) { case FONT_Em: @@ -950,14 +941,14 @@ pre_bf(DECL_ARGS) font_push('R'); break; } - return(1); + return 1; } static void post_bf(DECL_ARGS) { - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) font_pop(); } @@ -966,13 +957,13 @@ pre_bk(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: - return(1); - case MDOC_BODY: + case ROFFT_BLOCK: + return 1; + case ROFFT_BODY: outflags |= MMAN_Bk; - return(1); + return 1; default: - return(0); + return 0; } } @@ -980,7 +971,7 @@ static void post_bk(DECL_ARGS) { - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) outflags &= ~MMAN_Bk; } @@ -1002,21 +993,21 @@ pre_bl(DECL_ARGS) switch (n->norm->Bl.type) { case LIST_enum: n->norm->Bl.count = 0; - return(1); + return 1; case LIST_column: break; default: - return(1); + return 1; } - if (n->nchild) { + if (n->child != NULL) { print_line(".TS", MMAN_nl); for (icol = 0; icol < n->norm->Bl.ncols; icol++) print_word("l"); print_word("."); } outflags |= MMAN_nl; - return(1); + return 1; } static void @@ -1025,7 +1016,7 @@ post_bl(DECL_ARGS) switch (n->norm->Bl.type) { case LIST_column: - if (n->nchild) + if (n->child != NULL) print_line(".TE", 0); break; case LIST_enum: @@ -1056,7 +1047,7 @@ pre_br(DECL_ARGS) { outflags |= MMAN_br; - return(0); + return 0; } static int @@ -1071,12 +1062,12 @@ pre_bx(DECL_ARGS) } print_word("BSD"); if (NULL == n) - return(0); + return 0; outflags &= ~MMAN_spc; print_word("-"); outflags &= ~MMAN_spc; print_word(n->string); - return(0); + return 0; } static int @@ -1084,7 +1075,7 @@ pre_dl(DECL_ARGS) { print_offs("6n", 0); - return(1); + return 1; } static void @@ -1103,7 +1094,7 @@ pre_em(DECL_ARGS) { font_push('I'); - return(1); + return 1; } static int @@ -1112,11 +1103,11 @@ pre_en(DECL_ARGS) if (NULL == n->norm->Es || NULL == n->norm->Es->child) - return(1); + return 1; print_word(n->norm->Es->child->string); outflags &= ~MMAN_spc; - return(1); + return 1; } static void @@ -1146,7 +1137,7 @@ pre_eo(DECL_ARGS) n->parent->head->child != NULL && (n->child != NULL || (n->parent->tail != NULL && n->parent->tail->child != NULL))) outflags &= ~(MMAN_spc | MMAN_nl); - return(1); + return 1; } static void @@ -1189,7 +1180,7 @@ pre_fa(DECL_ARGS) if (NULL != (n = n->next)) print_word(","); } - return(0); + return 0; } static void @@ -1206,7 +1197,7 @@ pre_fd(DECL_ARGS) pre_syn(n); font_push('B'); - return(1); + return 1; } static void @@ -1223,9 +1214,9 @@ pre_fl(DECL_ARGS) font_push('B'); print_word("\\-"); - if (n->nchild) + if (n->child != NULL) outflags &= ~MMAN_spc; - return(1); + return 1; } static void @@ -1233,9 +1224,9 @@ post_fl(DECL_ARGS) { font_pop(); - if ( ! (n->nchild || + if (!(n->child != NULL || n->next == NULL || - n->next->type == MDOC_TEXT || + n->next->type == ROFFT_TEXT || n->next->flags & MDOC_LINE)) outflags &= ~MMAN_spc; } @@ -1248,7 +1239,7 @@ pre_fn(DECL_ARGS) n = n->child; if (NULL == n) - return(0); + return 0; if (MDOC_SYNPRETTY & n->flags) print_block(".HP 4n", MMAN_nl); @@ -1263,7 +1254,7 @@ pre_fn(DECL_ARGS) n = n->next; if (NULL != n) pre_fa(meta, n); - return(0); + return 0; } static void @@ -1282,17 +1273,17 @@ pre_fo(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: pre_syn(n); break; - case MDOC_HEAD: + case ROFFT_HEAD: if (n->child == NULL) - return(0); + return 0; if (MDOC_SYNPRETTY & n->flags) print_block(".HP 4n", MMAN_nl); font_push('B'); break; - case MDOC_BODY: + case ROFFT_BODY: outflags &= ~(MMAN_spc | MMAN_nl); print_word("("); outflags &= ~MMAN_spc; @@ -1300,7 +1291,7 @@ pre_fo(DECL_ARGS) default: break; } - return(1); + return 1; } static void @@ -1308,11 +1299,11 @@ post_fo(DECL_ARGS) { switch (n->type) { - case MDOC_HEAD: + case ROFFT_HEAD: if (n->child != NULL) font_pop(); break; - case MDOC_BODY: + case ROFFT_BODY: post_fn(meta, n); break; default: @@ -1326,7 +1317,7 @@ pre_ft(DECL_ARGS) pre_syn(n); font_push('I'); - return(1); + return 1; } static int @@ -1343,7 +1334,7 @@ pre_in(DECL_ARGS) outflags &= ~MMAN_spc; font_push('I'); } - return(1); + return 1; } static void @@ -1365,10 +1356,10 @@ post_in(DECL_ARGS) static int pre_it(DECL_ARGS) { - const struct mdoc_node *bln; + const struct roff_node *bln; switch (n->type) { - case MDOC_HEAD: + case ROFFT_HEAD: outflags |= MMAN_PP | MMAN_nl; bln = n->parent->parent; if (0 == bln->norm->Bl.comp || @@ -1378,22 +1369,18 @@ pre_it(DECL_ARGS) outflags &= ~MMAN_br; switch (bln->norm->Bl.type) { case LIST_item: - return(0); + return 0; case LIST_inset: - /* FALLTHROUGH */ case LIST_diag: - /* FALLTHROUGH */ case LIST_ohang: if (bln->norm->Bl.type == LIST_diag) print_line(".B \"", 0); else print_line(".R \"", 0); outflags &= ~MMAN_spc; - return(1); + return 1; case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: print_width(&bln->norm->Bl, NULL); TPremain = 0; @@ -1405,31 +1392,31 @@ pre_it(DECL_ARGS) print_word("-"); font_pop(); outflags |= MMAN_nl; - return(0); + return 0; case LIST_enum: print_width(&bln->norm->Bl, NULL); TPremain = 0; outflags |= MMAN_nl; print_count(&bln->norm->Bl.count); outflags |= MMAN_nl; - return(0); + return 0; case LIST_hang: print_width(&bln->norm->Bl, n->child); TPremain = 0; outflags |= MMAN_nl; - return(1); + return 1; case LIST_tag: print_width(&bln->norm->Bl, n->child); putchar('\n'); outflags &= ~MMAN_spc; - return(1); + return 1; default: - return(1); + return 1; } default: break; } - return(1); + return 1; } /* @@ -1462,12 +1449,12 @@ mid_it(void) static void post_it(DECL_ARGS) { - const struct mdoc_node *bln; + const struct roff_node *bln; bln = n->parent->parent; switch (n->type) { - case MDOC_HEAD: + case ROFFT_HEAD: switch (bln->norm->Bl.type) { case LIST_diag: outflags &= ~MMAN_spc; @@ -1480,18 +1467,13 @@ post_it(DECL_ARGS) break; } break; - case MDOC_BODY: + case ROFFT_BODY: switch (bln->norm->Bl.type) { case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_enum: - /* FALLTHROUGH */ case LIST_hang: - /* FALLTHROUGH */ case LIST_tag: assert(Bl_stack_len); Bl_stack[--Bl_stack_len] = 0; @@ -1532,10 +1514,10 @@ post_lb(DECL_ARGS) static int pre_lk(DECL_ARGS) { - const struct mdoc_node *link, *descr; + const struct roff_node *link, *descr; if (NULL == (link = n->child)) - return(0); + return 0; if (NULL != (descr = link->next)) { font_push('I'); @@ -1550,7 +1532,7 @@ pre_lk(DECL_ARGS) font_push('B'); print_word(link->string); font_pop(); - return(0); + return 0; } static int @@ -1558,7 +1540,7 @@ pre_ll(DECL_ARGS) { print_line(".ll", 0); - return(1); + return 1; } static int @@ -1566,7 +1548,7 @@ pre_li(DECL_ARGS) { font_push('R'); - return(1); + return 1; } static int @@ -1574,16 +1556,16 @@ pre_nm(DECL_ARGS) { char *name; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { outflags |= MMAN_Bk; pre_syn(n); } - if (MDOC_ELEM != n->type && MDOC_HEAD != n->type) - return(1); + if (n->type != ROFFT_ELEM && n->type != ROFFT_HEAD) + return 1; name = n->child ? n->child->string : meta->name; if (NULL == name) - return(0); - if (MDOC_HEAD == n->type) { + return 0; + if (n->type == ROFFT_HEAD) { if (NULL == n->parent->prev) outflags |= MMAN_sp; print_block(".HP", 0); @@ -1593,7 +1575,7 @@ pre_nm(DECL_ARGS) font_push('B'); if (NULL == n->child) print_word(meta->name); - return(1); + return 1; } static void @@ -1601,12 +1583,11 @@ post_nm(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: outflags &= ~MMAN_Bk; break; - case MDOC_HEAD: - /* FALLTHROUGH */ - case MDOC_ELEM: + case ROFFT_HEAD: + case ROFFT_ELEM: if (n->child != NULL || meta->name != NULL) font_pop(); break; @@ -1620,7 +1601,7 @@ pre_no(DECL_ARGS) { outflags |= MMAN_spc_force; - return(1); + return 1; } static int @@ -1628,7 +1609,7 @@ pre_ns(DECL_ARGS) { outflags &= ~MMAN_spc; - return(0); + return 0; } static void @@ -1647,7 +1628,7 @@ pre_pp(DECL_ARGS) outflags |= MMAN_PP; outflags |= MMAN_sp | MMAN_nl; outflags &= ~MMAN_br; - return(0); + return 0; } static int @@ -1658,40 +1639,39 @@ pre_rs(DECL_ARGS) outflags |= MMAN_PP | MMAN_sp | MMAN_nl; outflags &= ~MMAN_br; } - return(1); + return 1; } static int pre_rv(DECL_ARGS) { - int nchild; + struct roff_node *nch; outflags |= MMAN_br | MMAN_nl; - nchild = n->nchild; - if (nchild > 0) { + if (n->child != NULL) { print_word("The"); - for (n = n->child; n; n = n->next) { + for (nch = n->child; nch != NULL; nch = nch->next) { font_push('B'); - print_word(n->string); + print_word(nch->string); font_pop(); outflags &= ~MMAN_spc; print_word("()"); - if (n->next == NULL) + if (nch->next == NULL) continue; - if (nchild > 2) { + if (nch->prev != NULL || nch->next->next != NULL) { outflags &= ~MMAN_spc; print_word(","); } - if (n->next->next == NULL) + if (nch->next->next == NULL) print_word("and"); } - if (nchild > 1) + if (n->child != NULL && n->child->next != NULL) print_word("functions return"); else print_word("function returns"); @@ -1710,14 +1690,14 @@ pre_rv(DECL_ARGS) print_word("is set to indicate the error."); outflags |= MMAN_nl; - return(0); + return 0; } static int pre_skip(DECL_ARGS) { - return(0); + return 0; } static int @@ -1734,7 +1714,7 @@ pre_sm(DECL_ARGS) if (MMAN_Sm & outflags) outflags |= MMAN_spc; - return(0); + return 0; } static int @@ -1746,7 +1726,7 @@ pre_sp(DECL_ARGS) print_line(".PP", 0); } else print_line(".sp", 0); - return(1); + return 1; } static void @@ -1761,7 +1741,7 @@ pre_sy(DECL_ARGS) { font_push('B'); - return(1); + return 1; } static int @@ -1770,24 +1750,24 @@ pre_vt(DECL_ARGS) if (MDOC_SYNPRETTY & n->flags) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: pre_syn(n); - return(1); - case MDOC_BODY: + return 1; + case ROFFT_BODY: break; default: - return(0); + return 0; } } font_push('I'); - return(1); + return 1; } static void post_vt(DECL_ARGS) { - if (MDOC_SYNPRETTY & n->flags && MDOC_BODY != n->type) + if (n->flags & MDOC_SYNPRETTY && n->type != ROFFT_BODY) return; font_pop(); } @@ -1798,16 +1778,16 @@ pre_xr(DECL_ARGS) n = n->child; if (NULL == n) - return(0); + return 0; print_node(meta, n); n = n->next; if (NULL == n) - return(0); + return 0; outflags &= ~MMAN_spc; print_word("("); print_node(meta, n); print_word(")"); - return(0); + return 0; } static int @@ -1816,9 +1796,9 @@ pre_ux(DECL_ARGS) print_word(manacts[n->tok].prefix); if (NULL == n->child) - return(0); + return 0; outflags &= ~MMAN_spc; print_word("\\ "); outflags &= ~MMAN_spc; - return(1); + return 1; } diff --git a/usr/src/cmd/mandoc/mdoc_state.c b/usr/src/cmd/mandoc/mdoc_state.c new file mode 100644 index 0000000000..cbd7376309 --- /dev/null +++ b/usr/src/cmd/mandoc/mdoc_state.c @@ -0,0 +1,292 @@ +/* $Id: mdoc_state.c,v 1.3 2015/10/30 18:53:54 schwarze Exp $ */ +/* + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include <sys/types.h> + +#include <stdlib.h> +#include <string.h> + +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" +#include "libmandoc.h" +#include "libmdoc.h" + +#define STATE_ARGS struct roff_man *mdoc, struct roff_node *n + +typedef void (*state_handler)(STATE_ARGS); + +static void state_bd(STATE_ARGS); +static void state_bl(STATE_ARGS); +static void state_dl(STATE_ARGS); +static void state_sh(STATE_ARGS); +static void state_sm(STATE_ARGS); + +static const state_handler state_handlers[MDOC_MAX] = { + NULL, /* Ap */ + NULL, /* Dd */ + NULL, /* Dt */ + NULL, /* Os */ + state_sh, /* Sh */ + NULL, /* Ss */ + NULL, /* Pp */ + NULL, /* D1 */ + state_dl, /* Dl */ + state_bd, /* Bd */ + NULL, /* Ed */ + state_bl, /* Bl */ + NULL, /* El */ + NULL, /* It */ + NULL, /* Ad */ + NULL, /* An */ + NULL, /* Ar */ + NULL, /* Cd */ + NULL, /* Cm */ + NULL, /* Dv */ + NULL, /* Er */ + NULL, /* Ev */ + NULL, /* Ex */ + NULL, /* Fa */ + NULL, /* Fd */ + NULL, /* Fl */ + NULL, /* Fn */ + NULL, /* Ft */ + NULL, /* Ic */ + NULL, /* In */ + NULL, /* Li */ + NULL, /* Nd */ + NULL, /* Nm */ + NULL, /* Op */ + NULL, /* Ot */ + NULL, /* Pa */ + NULL, /* Rv */ + NULL, /* St */ + NULL, /* Va */ + NULL, /* Vt */ + NULL, /* Xr */ + NULL, /* %A */ + NULL, /* %B */ + NULL, /* %D */ + NULL, /* %I */ + NULL, /* %J */ + NULL, /* %N */ + NULL, /* %O */ + NULL, /* %P */ + NULL, /* %R */ + NULL, /* %T */ + NULL, /* %V */ + NULL, /* Ac */ + NULL, /* Ao */ + NULL, /* Aq */ + NULL, /* At */ + NULL, /* Bc */ + NULL, /* Bf */ + NULL, /* Bo */ + NULL, /* Bq */ + NULL, /* Bsx */ + NULL, /* Bx */ + NULL, /* Db */ + NULL, /* Dc */ + NULL, /* Do */ + NULL, /* Dq */ + NULL, /* Ec */ + NULL, /* Ef */ + NULL, /* Em */ + NULL, /* Eo */ + NULL, /* Fx */ + NULL, /* Ms */ + NULL, /* No */ + NULL, /* Ns */ + NULL, /* Nx */ + NULL, /* Ox */ + NULL, /* Pc */ + NULL, /* Pf */ + NULL, /* Po */ + NULL, /* Pq */ + NULL, /* Qc */ + NULL, /* Ql */ + NULL, /* Qo */ + NULL, /* Qq */ + NULL, /* Re */ + NULL, /* Rs */ + NULL, /* Sc */ + NULL, /* So */ + NULL, /* Sq */ + state_sm, /* Sm */ + NULL, /* Sx */ + NULL, /* Sy */ + NULL, /* Tn */ + NULL, /* Ux */ + NULL, /* Xc */ + NULL, /* Xo */ + NULL, /* Fo */ + NULL, /* Fc */ + NULL, /* Oo */ + NULL, /* Oc */ + NULL, /* Bk */ + NULL, /* Ek */ + NULL, /* Bt */ + NULL, /* Hf */ + NULL, /* Fr */ + NULL, /* Ud */ + NULL, /* Lb */ + NULL, /* Lp */ + NULL, /* Lk */ + NULL, /* Mt */ + NULL, /* Brq */ + NULL, /* Bro */ + NULL, /* Brc */ + NULL, /* %C */ + NULL, /* Es */ + NULL, /* En */ + NULL, /* Dx */ + NULL, /* %Q */ + NULL, /* br */ + NULL, /* sp */ + NULL, /* %U */ + NULL, /* Ta */ + NULL, /* ll */ +}; + + +void +mdoc_state(struct roff_man *mdoc, struct roff_node *n) +{ + state_handler handler; + + if (n->tok == TOKEN_NONE) + return; + + if ( ! (mdoc_macros[n->tok].flags & MDOC_PROLOGUE)) + mdoc->flags |= MDOC_PBODY; + + handler = state_handlers[n->tok]; + if (*handler) + (*handler)(mdoc, n); +} + +void +mdoc_state_reset(struct roff_man *mdoc) +{ + + roff_setreg(mdoc->roff, "nS", 0, '='); + mdoc->flags = 0; +} + +static void +state_bd(STATE_ARGS) +{ + enum mdocargt arg; + + if (n->type != ROFFT_HEAD && + (n->type != ROFFT_BODY || n->end != ENDBODY_NOT)) + return; + + if (n->parent->args == NULL) + return; + + arg = n->parent->args->argv[0].arg; + if (arg != MDOC_Literal && arg != MDOC_Unfilled) + return; + + state_dl(mdoc, n); +} + +static void +state_bl(STATE_ARGS) +{ + + if (n->type != ROFFT_HEAD || n->parent->args == NULL) + return; + + switch(n->parent->args->argv[0].arg) { + case MDOC_Diag: + n->norm->Bl.type = LIST_diag; + break; + case MDOC_Column: + n->norm->Bl.type = LIST_column; + break; + default: + break; + } +} + +static void +state_dl(STATE_ARGS) +{ + + switch (n->type) { + case ROFFT_HEAD: + mdoc->flags |= MDOC_LITERAL; + break; + case ROFFT_BODY: + mdoc->flags &= ~MDOC_LITERAL; + break; + default: + break; + } +} + +static void +state_sh(STATE_ARGS) +{ + struct roff_node *nch; + char *secname; + + if (n->type != ROFFT_HEAD) + return; + + if ( ! (n->flags & MDOC_VALID)) { + secname = NULL; + deroff(&secname, n); + + /* + * Set the section attribute for the BLOCK, HEAD, + * and HEAD children; the latter can only be TEXT + * nodes, so no recursion is needed. For other + * nodes, including the .Sh BODY, this is done + * when allocating the node data structures, but + * for .Sh BLOCK and HEAD, the section is still + * unknown at that time. + */ + + n->sec = n->parent->sec = secname == NULL ? + SEC_CUSTOM : mdoc_a2sec(secname); + for (nch = n->child; nch != NULL; nch = nch->next) + nch->sec = n->sec; + free(secname); + } + + if ((mdoc->lastsec = n->sec) == SEC_SYNOPSIS) { + roff_setreg(mdoc->roff, "nS", 1, '='); + mdoc->flags |= MDOC_SYNOPSIS; + } else { + roff_setreg(mdoc->roff, "nS", 0, '='); + mdoc->flags &= ~MDOC_SYNOPSIS; + } +} + +static void +state_sm(STATE_ARGS) +{ + + if (n->child == NULL) + mdoc->flags ^= MDOC_SMOFF; + else if ( ! strcmp(n->child->string, "on")) + mdoc->flags &= ~MDOC_SMOFF; + else if ( ! strcmp(n->child->string, "off")) + mdoc->flags |= MDOC_SMOFF; +} diff --git a/usr/src/cmd/mandoc/mdoc_term.c b/usr/src/cmd/mandoc/mdoc_term.c index 20c47d6668..e846436273 100644 --- a/usr/src/cmd/mandoc/mdoc_term.c +++ b/usr/src/cmd/mandoc/mdoc_term.c @@ -1,16 +1,16 @@ -/* $Id: mdoc_term.c,v 1.313 2015/03/06 15:48:52 schwarze Exp $ */ +/* $Id: mdoc_term.c,v 1.331 2016/01/08 17:48:09 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010, 2012-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010, 2012-2016 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2013 Franco Fichtner <franco@lastsummer.de> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -28,11 +28,13 @@ #include <stdlib.h> #include <string.h> -#include "mandoc.h" #include "mandoc_aux.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" #include "out.h" #include "term.h" -#include "mdoc.h" +#include "tag.h" #include "main.h" struct termpair { @@ -42,8 +44,8 @@ struct termpair { #define DECL_ARGS struct termp *p, \ struct termpair *pair, \ - const struct mdoc_meta *meta, \ - struct mdoc_node *n + const struct roff_meta *meta, \ + struct roff_node *n struct termact { int (*pre)(DECL_ARGS); @@ -53,14 +55,14 @@ struct termact { static int a2width(const struct termp *, const char *); static void print_bvspace(struct termp *, - const struct mdoc_node *, - const struct mdoc_node *); + const struct roff_node *, + const struct roff_node *); static void print_mdoc_node(DECL_ARGS); static void print_mdoc_nodelist(DECL_ARGS); -static void print_mdoc_head(struct termp *, const void *); -static void print_mdoc_foot(struct termp *, const void *); +static void print_mdoc_head(struct termp *, const struct roff_meta *); +static void print_mdoc_foot(struct termp *, const struct roff_meta *); static void synopsis_pre(struct termp *, - const struct mdoc_node *); + const struct roff_node *); static void termp____post(DECL_ARGS); static void termp__t_post(DECL_ARGS); @@ -93,6 +95,7 @@ static int termp_bx_pre(DECL_ARGS); static int termp_cd_pre(DECL_ARGS); static int termp_d1_pre(DECL_ARGS); static int termp_eo_pre(DECL_ARGS); +static int termp_er_pre(DECL_ARGS); static int termp_ex_pre(DECL_ARGS); static int termp_fa_pre(DECL_ARGS); static int termp_fd_pre(DECL_ARGS); @@ -116,6 +119,7 @@ static int termp_skip_pre(DECL_ARGS); static int termp_sm_pre(DECL_ARGS); static int termp_sp_pre(DECL_ARGS); static int termp_ss_pre(DECL_ARGS); +static int termp_tag_pre(DECL_ARGS); static int termp_under_pre(DECL_ARGS); static int termp_ud_pre(DECL_ARGS); static int termp_vt_pre(DECL_ARGS); @@ -142,9 +146,9 @@ static const struct termact termacts[MDOC_MAX] = { { termp_under_pre, NULL }, /* Ar */ { termp_cd_pre, NULL }, /* Cd */ { termp_bold_pre, NULL }, /* Cm */ - { NULL, NULL }, /* Dv */ - { NULL, NULL }, /* Er */ - { NULL, NULL }, /* Ev */ + { termp_li_pre, NULL }, /* Dv */ + { termp_er_pre, NULL }, /* Er */ + { termp_tag_pre, NULL }, /* Ev */ { termp_ex_pre, NULL }, /* Ex */ { termp_fa_pre, NULL }, /* Fa */ { termp_fd_pre, termp_fd_post }, /* Fd */ @@ -248,29 +252,27 @@ static const struct termact termacts[MDOC_MAX] = { { termp_ll_pre, NULL }, /* ll */ }; +static int fn_prio; void -terminal_mdoc(void *arg, const struct mdoc *mdoc) +terminal_mdoc(void *arg, const struct roff_man *mdoc) { - const struct mdoc_meta *meta; - struct mdoc_node *n; + struct roff_node *n; struct termp *p; p = (struct termp *)arg; - p->overstep = 0; p->rmargin = p->maxrmargin = p->defrmargin; p->tabwidth = term_len(p, 5); - n = mdoc_node(mdoc)->child; - meta = mdoc_meta(mdoc); - + n = mdoc->first->child; if (p->synopsisonly) { while (n != NULL) { if (n->tok == MDOC_Sh && n->sec == SEC_SYNOPSIS) { if (n->child->next->child != NULL) print_mdoc_nodelist(p, NULL, - meta, n->child->next->child); + &mdoc->meta, + n->child->next->child); term_newln(p); break; } @@ -279,11 +281,12 @@ terminal_mdoc(void *arg, const struct mdoc *mdoc) } else { if (p->defindent == 0) p->defindent = 5; - term_begin(p, print_mdoc_head, print_mdoc_foot, meta); + term_begin(p, print_mdoc_head, print_mdoc_foot, + &mdoc->meta); if (n != NULL) { if (n->tok != MDOC_Sh) term_vspace(p); - print_mdoc_nodelist(p, NULL, meta, n); + print_mdoc_nodelist(p, NULL, &mdoc->meta, n); } term_end(p); } @@ -331,7 +334,7 @@ print_mdoc_node(DECL_ARGS) */ switch (n->type) { - case MDOC_TEXT: + case ROFFT_TEXT: if (' ' == *n->string && MDOC_LINE & n->flags) term_newln(p); if (MDOC_DELIMC & n->flags) @@ -340,21 +343,21 @@ print_mdoc_node(DECL_ARGS) if (MDOC_DELIMO & n->flags) p->flags |= TERMP_NOSPACE; break; - case MDOC_EQN: + case ROFFT_EQN: if ( ! (n->flags & MDOC_LINE)) p->flags |= TERMP_NOSPACE; term_eqn(p, n->eqn); if (n->next != NULL && ! (n->next->flags & MDOC_LINE)) p->flags |= TERMP_NOSPACE; break; - case MDOC_TBL: + case ROFFT_TBL: if (p->tbl.cols == NULL) term_newln(p); term_tbl(p, n->span); break; default: if (termacts[n->tok].pre && - (n->end == ENDBODY_NOT || n->nchild)) + (n->end == ENDBODY_NOT || n->child != NULL)) chld = (*termacts[n->tok].pre) (p, &npair, meta, n); break; @@ -367,11 +370,11 @@ print_mdoc_node(DECL_ARGS) (ENDBODY_NOT == n->end ? n : n->body)->prev_font); switch (n->type) { - case MDOC_TEXT: + case ROFFT_TEXT: break; - case MDOC_TBL: + case ROFFT_TBL: break; - case MDOC_EQN: + case ROFFT_EQN: break; default: if ( ! termacts[n->tok].post || MDOC_ENDED & n->flags) @@ -406,13 +409,10 @@ print_mdoc_node(DECL_ARGS) } static void -print_mdoc_foot(struct termp *p, const void *arg) +print_mdoc_foot(struct termp *p, const struct roff_meta *meta) { - const struct mdoc_meta *meta; size_t sz; - meta = (const struct mdoc_meta *)arg; - term_fontrepl(p, TERMFONT_NONE); /* @@ -458,14 +458,11 @@ print_mdoc_foot(struct termp *p, const void *arg) } static void -print_mdoc_head(struct termp *p, const void *arg) +print_mdoc_head(struct termp *p, const struct roff_meta *meta) { - const struct mdoc_meta *meta; char *volume, *title; size_t vollen, titlen; - meta = (const struct mdoc_meta *)arg; - /* * The header is strange. It has three components, which are * really two with the first duplicated. It goes like this: @@ -538,7 +535,7 @@ a2width(const struct termp *p, const char *v) SCALE_HS_INIT(&su, term_strlen(p, v)); su.scale /= term_strlen(p, "0"); } - return(term_hspan(p, &su)); + return term_hspan(p, &su) / 24; } /* @@ -548,10 +545,10 @@ a2width(const struct termp *p, const char *v) */ static void print_bvspace(struct termp *p, - const struct mdoc_node *bl, - const struct mdoc_node *n) + const struct roff_node *bl, + const struct roff_node *n) { - const struct mdoc_node *nn; + const struct roff_node *nn; assert(n); @@ -568,9 +565,9 @@ print_bvspace(struct termp *p, while (nn->prev == NULL) { do { nn = nn->parent; - if (nn->type == MDOC_ROOT) + if (nn->type == ROFFT_ROOT) return; - } while (nn->type != MDOC_BLOCK); + } while (nn->type != ROFFT_BLOCK); if (nn->tok == MDOC_Sh || nn->tok == MDOC_Ss) return; if (nn->tok == MDOC_It && @@ -601,22 +598,22 @@ static int termp_ll_pre(DECL_ARGS) { - term_setwidth(p, n->nchild ? n->child->string : NULL); - return(0); + term_setwidth(p, n->child != NULL ? n->child->string : NULL); + return 0; } static int termp_it_pre(DECL_ARGS) { char buf[24]; - const struct mdoc_node *bl, *nn; + const struct roff_node *bl, *nn; size_t ncols, dcol; int i, offset, width; enum mdoc_list type; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { print_bvspace(p, n->parent->parent, n); - return(1); + return 1; } bl = n->parent->parent->parent; @@ -628,11 +625,8 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_enum: width = term_len(p, 2); break; @@ -640,7 +634,6 @@ termp_it_pre(DECL_ARGS) width = term_len(p, 8); break; case LIST_column: - /* FALLTHROUGH */ case LIST_tag: width = term_len(p, 10); break; @@ -666,7 +659,7 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_column: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) break; /* @@ -683,8 +676,8 @@ termp_it_pre(DECL_ARGS) ncols == 5 ? term_len(p, 3) : term_len(p, 1); /* - * Calculate the offset by applying all prior MDOC_BODY, - * so we stop at the MDOC_HEAD (NULL == nn->prev). + * Calculate the offset by applying all prior ROFFT_BODY, + * so we stop at the ROFFT_HEAD (nn->prev == NULL). */ for (i = 0, nn = n->prev; @@ -734,11 +727,11 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_diag: - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) term_word(p, "\\ \\ "); break; case LIST_inset: - if (MDOC_BODY == n->type && n->parent->head->nchild) + if (n->type == ROFFT_BODY && n->parent->head->child != NULL) term_word(p, "\\ "); break; default: @@ -749,7 +742,7 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_diag: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) term_fontpush(p, TERMFONT_BOLD); break; default: @@ -765,25 +758,22 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_enum: + case LIST_bullet: + case LIST_dash: + case LIST_hyphen: /* * Weird special case. * Some very narrow lists actually hang. */ - /* FALLTHROUGH */ - case LIST_bullet: - /* FALLTHROUGH */ - case LIST_dash: - /* FALLTHROUGH */ - case LIST_hyphen: if (width <= (int)term_len(p, 2)) p->flags |= TERMP_HANG; - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK; p->trailspace = 1; break; case LIST_hang: - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; /* @@ -802,17 +792,17 @@ termp_it_pre(DECL_ARGS) p->trailspace = 1; break; case LIST_tag: - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; - p->flags |= TERMP_NOBREAK | TERMP_BRIND; + p->flags |= TERMP_NOBREAK | TERMP_BRTRSP | TERMP_BRIND; p->trailspace = 2; if (NULL == n->next || NULL == n->next->child) p->flags |= TERMP_DANGLE; break; case LIST_column: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) break; if (NULL == n->next) { @@ -825,7 +815,7 @@ termp_it_pre(DECL_ARGS) break; case LIST_diag: - if (MDOC_HEAD != n->type) + if (n->type != ROFFT_HEAD) break; p->flags |= TERMP_NOBREAK | TERMP_BRIND; p->trailspace = 1; @@ -849,7 +839,7 @@ termp_it_pre(DECL_ARGS) * don't want to recalculate rmargin and offsets when * using `Bd' or `Bl' within `-hang' overstep lists. */ - if (MDOC_HEAD == n->type && + if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child && (MDOC_Bl == n->next->child->tok || @@ -857,15 +847,11 @@ termp_it_pre(DECL_ARGS) break; /* FALLTHROUGH */ case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_enum: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_tag: - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) p->rmargin = p->offset + width; else p->offset += width; @@ -877,7 +863,7 @@ termp_it_pre(DECL_ARGS) * XXX - this behaviour is not documented: the * right-most column is filled to the right margin. */ - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) break; if (NULL == n->next && p->rmargin < p->maxrmargin) p->rmargin = p->maxrmargin; @@ -891,7 +877,7 @@ termp_it_pre(DECL_ARGS) * HEAD character (temporarily bold, in some cases). */ - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) switch (type) { case LIST_bullet: term_fontpush(p, TERMFONT_BOLD); @@ -899,10 +885,9 @@ termp_it_pre(DECL_ARGS) term_fontpop(p); break; case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: term_fontpush(p, TERMFONT_BOLD); - term_word(p, "\\(hy"); + term_word(p, "-"); term_fontpop(p); break; case LIST_enum: @@ -921,26 +906,22 @@ termp_it_pre(DECL_ARGS) switch (type) { case LIST_bullet: - /* FALLTHROUGH */ case LIST_item: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: - /* FALLTHROUGH */ case LIST_enum: - if (MDOC_HEAD == n->type) - return(0); + if (n->type == ROFFT_HEAD) + return 0; break; case LIST_column: - if (MDOC_HEAD == n->type) - return(0); + if (n->type == ROFFT_HEAD) + return 0; break; default: break; } - return(1); + return 1; } static void @@ -948,22 +929,20 @@ termp_it_post(DECL_ARGS) { enum mdoc_list type; - if (MDOC_BLOCK == n->type) + if (n->type == ROFFT_BLOCK) return; type = n->parent->parent->parent->norm->Bl.type; switch (type) { case LIST_item: - /* FALLTHROUGH */ case LIST_diag: - /* FALLTHROUGH */ case LIST_inset: - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) term_newln(p); break; case LIST_column: - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) term_flushln(p); break; default: @@ -977,7 +956,7 @@ termp_it_post(DECL_ARGS) * has munged them in the meanwhile. */ - p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | + p->flags &= ~(TERMP_NOBREAK | TERMP_BRTRSP | TERMP_BRIND | TERMP_DANGLE | TERMP_HANG); p->trailspace = 0; } @@ -987,14 +966,14 @@ termp_nm_pre(DECL_ARGS) { const char *cp; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { p->flags |= TERMP_PREKEEP; - return(1); + return 1; } - if (MDOC_BODY == n->type) { + if (n->type == ROFFT_BODY) { if (NULL == n->child) - return(0); + return 0; p->flags |= TERMP_NOSPACE; cp = NULL; if (n->prev->child != NULL) @@ -1005,23 +984,23 @@ termp_nm_pre(DECL_ARGS) p->offset += term_len(p, 6); else p->offset += term_len(p, 1) + term_strlen(p, cp); - return(1); + return 1; } if (NULL == n->child && NULL == meta->name) - return(0); + return 0; - if (MDOC_HEAD == n->type) + if (n->type == ROFFT_HEAD) synopsis_pre(p, n->parent); - if (MDOC_HEAD == n->type && + if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child) { p->flags |= TERMP_NOSPACE | TERMP_NOBREAK | TERMP_BRIND; p->trailspace = 1; p->rmargin = p->offset + term_len(p, 1); if (NULL == n->child) { p->rmargin += term_strlen(p, meta->name); - } else if (MDOC_TEXT == n->child->type) { + } else if (n->child->type == ROFFT_TEXT) { p->rmargin += term_strlen(p, n->child->string); if (n->child->next) p->flags |= TERMP_HANG; @@ -1034,21 +1013,21 @@ termp_nm_pre(DECL_ARGS) term_fontpush(p, TERMFONT_BOLD); if (NULL == n->child) term_word(p, meta->name); - return(1); + return 1; } static void termp_nm_post(DECL_ARGS) { - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP); - } else if (MDOC_HEAD == n->type && + } else if (n->type == ROFFT_HEAD && NULL != n->next && NULL != n->next->child) { term_flushln(p); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG); p->trailspace = 0; - } else if (MDOC_BODY == n->type && n->child) + } else if (n->type == ROFFT_BODY && n->child != NULL) term_flushln(p); } @@ -1056,16 +1035,17 @@ static int termp_fl_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); term_word(p, "\\-"); - if ( ! (n->nchild == 0 && + if (!(n->child == NULL && (n->next == NULL || - n->next->type == MDOC_TEXT || + n->next->type == ROFFT_TEXT || n->next->flags & MDOC_LINE))) p->flags |= TERMP_NOSPACE; - return(1); + return 1; } static int @@ -1076,7 +1056,7 @@ termp__a_pre(DECL_ARGS) if (NULL == n->next || MDOC__A != n->next->tok) term_word(p, "and"); - return(1); + return 1; } static int @@ -1086,12 +1066,12 @@ termp_an_pre(DECL_ARGS) if (n->norm->An.auth == AUTH_split) { p->flags &= ~TERMP_NOSPLIT; p->flags |= TERMP_SPLIT; - return(0); + return 0; } if (n->norm->An.auth == AUTH_nosplit) { p->flags &= ~TERMP_SPLIT; p->flags |= TERMP_NOSPLIT; - return(0); + return 0; } if (p->flags & TERMP_SPLIT) @@ -1100,7 +1080,7 @@ termp_an_pre(DECL_ARGS) if (n->sec == SEC_AUTHORS && ! (p->flags & TERMP_NOSPLIT)) p->flags |= TERMP_SPLIT; - return(1); + return 1; } static int @@ -1109,7 +1089,7 @@ termp_ns_pre(DECL_ARGS) if ( ! (MDOC_LINE & n->flags)) p->flags |= TERMP_NOSPACE; - return(1); + return 1; } static int @@ -1117,43 +1097,42 @@ termp_rs_pre(DECL_ARGS) { if (SEC_SEE_ALSO != n->sec) - return(1); - if (MDOC_BLOCK == n->type && n->prev) + return 1; + if (n->type == ROFFT_BLOCK && n->prev != NULL) term_vspace(p); - return(1); + return 1; } static int termp_rv_pre(DECL_ARGS) { - int nchild; + struct roff_node *nch; term_newln(p); - nchild = n->nchild; - if (nchild > 0) { + if (n->child != NULL) { term_word(p, "The"); - for (n = n->child; n; n = n->next) { + for (nch = n->child; nch != NULL; nch = nch->next) { term_fontpush(p, TERMFONT_BOLD); - term_word(p, n->string); + term_word(p, nch->string); term_fontpop(p); p->flags |= TERMP_NOSPACE; term_word(p, "()"); - if (n->next == NULL) + if (nch->next == NULL) continue; - if (nchild > 2) { + if (nch->prev != NULL || nch->next->next != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } - if (n->next->next == NULL) + if (nch->next->next == NULL) term_word(p, "and"); } - if (nchild > 1) + if (n->child != NULL && n->child->next != NULL) term_word(p, "functions return"); else term_word(p, "function returns"); @@ -1173,33 +1152,35 @@ termp_rv_pre(DECL_ARGS) term_word(p, "is set to indicate the error."); p->flags |= TERMP_SENTENCE; - return(0); + return 0; } static int termp_ex_pre(DECL_ARGS) { - int nchild; + struct roff_node *nch; term_newln(p); term_word(p, "The"); - nchild = n->nchild; - for (n = n->child; n; n = n->next) { + for (nch = n->child; nch != NULL; nch = nch->next) { term_fontpush(p, TERMFONT_BOLD); - term_word(p, n->string); + term_word(p, nch->string); term_fontpop(p); - if (nchild > 2 && n->next) { + if (nch->next == NULL) + continue; + + if (nch->prev != NULL || nch->next->next != NULL) { p->flags |= TERMP_NOSPACE; term_word(p, ","); } - if (n->next && NULL == n->next->next) + if (nch->next->next == NULL) term_word(p, "and"); } - if (nchild > 1) + if (n->child != NULL && n->child->next != NULL) term_word(p, "utilities exit\\~0"); else term_word(p, "utility exits\\~0"); @@ -1207,30 +1188,30 @@ termp_ex_pre(DECL_ARGS) term_word(p, "on success, and\\~>0 if an error occurs."); p->flags |= TERMP_SENTENCE; - return(0); + return 0; } static int termp_nd_pre(DECL_ARGS) { - if (n->type == MDOC_BODY) + if (n->type == ROFFT_BODY) term_word(p, "\\(en"); - return(1); + return 1; } static int termp_bl_pre(DECL_ARGS) { - return(MDOC_HEAD != n->type); + return n->type != ROFFT_HEAD; } static void termp_bl_post(DECL_ARGS) { - if (MDOC_BLOCK == n->type) + if (n->type == ROFFT_BLOCK) term_newln(p); } @@ -1239,25 +1220,25 @@ termp_xr_pre(DECL_ARGS) { if (NULL == (n = n->child)) - return(0); + return 0; - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_word(p, n->string); if (NULL == (n = n->next)) - return(0); + return 0; p->flags |= TERMP_NOSPACE; term_word(p, "("); p->flags |= TERMP_NOSPACE; - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_word(p, n->string); p->flags |= TERMP_NOSPACE; term_word(p, ")"); - return(0); + return 0; } /* @@ -1266,7 +1247,7 @@ termp_xr_pre(DECL_ARGS) * macro combos). */ static void -synopsis_pre(struct termp *p, const struct mdoc_node *n) +synopsis_pre(struct termp *p, const struct roff_node *n) { /* * Obviously, if we're not in a SYNOPSIS or no prior macros @@ -1295,13 +1276,9 @@ synopsis_pre(struct termp *p, const struct mdoc_node *n) */ switch (n->prev->tok) { case MDOC_Fd: - /* FALLTHROUGH */ case MDOC_Fn: - /* FALLTHROUGH */ case MDOC_Fo: - /* FALLTHROUGH */ case MDOC_In: - /* FALLTHROUGH */ case MDOC_Vt: term_vspace(p); break; @@ -1321,24 +1298,25 @@ static int termp_vt_pre(DECL_ARGS) { - if (MDOC_ELEM == n->type) { + if (n->type == ROFFT_ELEM) { synopsis_pre(p, n); - return(termp_under_pre(p, pair, meta, n)); - } else if (MDOC_BLOCK == n->type) { + return termp_under_pre(p, pair, meta, n); + } else if (n->type == ROFFT_BLOCK) { synopsis_pre(p, n); - return(1); - } else if (MDOC_HEAD == n->type) - return(0); + return 1; + } else if (n->type == ROFFT_HEAD) + return 0; - return(termp_under_pre(p, pair, meta, n)); + return termp_under_pre(p, pair, meta, n); } static int termp_bold_pre(DECL_ARGS) { + termp_tag_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_BOLD); - return(1); + return 1; } static int @@ -1346,7 +1324,7 @@ termp_fd_pre(DECL_ARGS) { synopsis_pre(p, n); - return(termp_bold_pre(p, pair, meta, n)); + return termp_bold_pre(p, pair, meta, n); } static void @@ -1361,29 +1339,37 @@ termp_sh_pre(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: /* * Vertical space before sections, except * when the previous section was empty. */ if (n->prev == NULL || - MDOC_Sh != n->prev->tok || + n->prev->tok != MDOC_Sh || (n->prev->body != NULL && n->prev->body->child != NULL)) term_vspace(p); break; - case MDOC_HEAD: + case ROFFT_HEAD: term_fontpush(p, TERMFONT_BOLD); break; - case MDOC_BODY: + case ROFFT_BODY: p->offset = term_len(p, p->defindent); - if (SEC_AUTHORS == n->sec) + switch (n->sec) { + case SEC_DESCRIPTION: + fn_prio = 0; + break; + case SEC_AUTHORS: p->flags &= ~(TERMP_SPLIT|TERMP_NOSPLIT); + break; + default: + break; + } break; default: break; } - return(1); + return 1; } static void @@ -1391,10 +1377,10 @@ termp_sh_post(DECL_ARGS) { switch (n->type) { - case MDOC_HEAD: + case ROFFT_HEAD: term_newln(p); break; - case MDOC_BODY: + case ROFFT_BODY: term_newln(p); p->offset = 0; break; @@ -1409,7 +1395,7 @@ termp_bt_pre(DECL_ARGS) term_word(p, "is currently in beta test."); p->flags |= TERMP_SENTENCE; - return(0); + return 0; } static void @@ -1426,18 +1412,18 @@ termp_ud_pre(DECL_ARGS) term_word(p, "currently under development."); p->flags |= TERMP_SENTENCE; - return(0); + return 0; } static int termp_d1_pre(DECL_ARGS) { - if (MDOC_BLOCK != n->type) - return(1); + if (n->type != ROFFT_BLOCK) + return 1; term_newln(p); p->offset += term_len(p, p->defindent + 1); - return(1); + return 1; } static int @@ -1447,7 +1433,7 @@ termp_ft_pre(DECL_ARGS) /* NB: MDOC_LINE does not effect this! */ synopsis_pre(p, n); term_fontpush(p, TERMFONT_UNDER); - return(1); + return 1; } static int @@ -1461,7 +1447,7 @@ termp_fn_pre(DECL_ARGS) synopsis_pre(p, n); if (NULL == (n = n->child)) - return(0); + return 0; if (pretty) { rmargin = p->rmargin; @@ -1469,11 +1455,14 @@ termp_fn_pre(DECL_ARGS) p->flags |= TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG; } - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_fontpush(p, TERMFONT_BOLD); term_word(p, n->string); term_fontpop(p); + if (n->sec == SEC_DESCRIPTION) + tag_put(n->string, ++fn_prio, p->line); + if (pretty) { term_flushln(p); p->flags &= ~(TERMP_NOBREAK | TERMP_BRIND | TERMP_HANG); @@ -1486,7 +1475,7 @@ termp_fn_pre(DECL_ARGS) p->flags |= TERMP_NOSPACE; for (n = n->next; n; n = n->next) { - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); term_fontpush(p, TERMFONT_UNDER); if (pretty) p->flags |= TERMP_NBRWORD; @@ -1508,17 +1497,17 @@ termp_fn_pre(DECL_ARGS) term_flushln(p); } - return(0); + return 0; } static int termp_fa_pre(DECL_ARGS) { - const struct mdoc_node *nn; + const struct roff_node *nn; if (n->parent->tok != MDOC_Fo) { term_fontpush(p, TERMFONT_UNDER); - return(1); + return 1; } for (nn = n->child; nn; nn = nn->next) { @@ -1533,21 +1522,21 @@ termp_fa_pre(DECL_ARGS) } } - return(0); + return 0; } static int termp_bd_pre(DECL_ARGS) { size_t tabwidth, lm, len, rm, rmax; - struct mdoc_node *nn; + struct roff_node *nn; int offset; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { print_bvspace(p, n, n); - return(1); - } else if (MDOC_HEAD == n->type) - return(0); + return 1; + } else if (n->type == ROFFT_HEAD) + return 0; /* Handle the -offset argument. */ @@ -1577,7 +1566,7 @@ termp_bd_pre(DECL_ARGS) if (DISP_literal != n->norm->Bd.type && DISP_unfilled != n->norm->Bd.type && DISP_centered != n->norm->Bd.type) - return(1); + return 1; tabwidth = p->tabwidth; if (DISP_literal == n->norm->Bd.type) @@ -1590,7 +1579,7 @@ termp_bd_pre(DECL_ARGS) for (nn = n->child; nn; nn = nn->next) { if (DISP_centered == n->norm->Bd.type) { - if (MDOC_TEXT == nn->type) { + if (nn->type == ROFFT_TEXT) { len = term_strlen(p, nn->string); p->offset = len >= rm ? 0 : lm + len >= rm ? rm - len : @@ -1607,19 +1596,12 @@ termp_bd_pre(DECL_ARGS) */ switch (nn->tok) { case MDOC_Sm: - /* FALLTHROUGH */ case MDOC_br: - /* FALLTHROUGH */ case MDOC_sp: - /* FALLTHROUGH */ case MDOC_Bl: - /* FALLTHROUGH */ case MDOC_D1: - /* FALLTHROUGH */ case MDOC_Dl: - /* FALLTHROUGH */ case MDOC_Lp: - /* FALLTHROUGH */ case MDOC_Pp: continue; default: @@ -1635,7 +1617,7 @@ termp_bd_pre(DECL_ARGS) p->tabwidth = tabwidth; p->rmargin = rm; p->maxrmargin = rmax; - return(0); + return 0; } static void @@ -1643,7 +1625,7 @@ termp_bd_post(DECL_ARGS) { size_t rm, rmax; - if (MDOC_BODY != n->type) + if (n->type != ROFFT_BODY) return; rm = p->rmargin; @@ -1670,7 +1652,7 @@ termp_bx_pre(DECL_ARGS) term_word(p, "BSD"); } else { term_word(p, "BSD"); - return(0); + return 0; } if (NULL != (n = n->next)) { @@ -1680,7 +1662,7 @@ termp_bx_pre(DECL_ARGS) term_word(p, n->string); } - return(0); + return 0; } static int @@ -1711,7 +1693,6 @@ termp_xx_pre(DECL_ARGS) break; default: abort(); - /* NOTREACHED */ } term_word(p, pp); @@ -1721,7 +1702,7 @@ termp_xx_pre(DECL_ARGS) term_word(p, n->child->string); p->flags = flags; } - return(0); + return 0; } static void @@ -1737,30 +1718,30 @@ termp_ss_pre(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: term_newln(p); if (n->prev) term_vspace(p); break; - case MDOC_HEAD: + case ROFFT_HEAD: term_fontpush(p, TERMFONT_BOLD); p->offset = term_len(p, (p->defindent+1)/2); break; - case MDOC_BODY: + case ROFFT_BODY: p->offset = term_len(p, p->defindent); break; default: break; } - return(1); + return 1; } static void termp_ss_post(DECL_ARGS) { - if (n->type == MDOC_HEAD || n->type == MDOC_BODY) + if (n->type == ROFFT_HEAD || n->type == ROFFT_BODY) term_newln(p); } @@ -1770,7 +1751,7 @@ termp_cd_pre(DECL_ARGS) synopsis_pre(p, n); term_fontpush(p, TERMFONT_BOLD); - return(1); + return 1; } static int @@ -1789,7 +1770,7 @@ termp_in_pre(DECL_ARGS) } p->flags |= TERMP_NOSPACE; - return(1); + return 1; } static void @@ -1826,6 +1807,7 @@ termp_sp_pre(DECL_ARGS) break; default: len = 1; + fn_prio = 0; break; } @@ -1837,115 +1819,97 @@ termp_sp_pre(DECL_ARGS) for (i = 0; i < len; i++) term_vspace(p); - return(0); + return 0; } static int termp_skip_pre(DECL_ARGS) { - return(0); + return 0; } static int termp_quote_pre(DECL_ARGS) { - if (MDOC_BODY != n->type && MDOC_ELEM != n->type) - return(1); + if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) + return 1; switch (n->tok) { case MDOC_Ao: - /* FALLTHROUGH */ case MDOC_Aq: - term_word(p, n->nchild == 1 && + term_word(p, n->child != NULL && n->child->next == NULL && n->child->tok == MDOC_Mt ? "<" : "\\(la"); break; case MDOC_Bro: - /* FALLTHROUGH */ case MDOC_Brq: term_word(p, "{"); break; case MDOC_Oo: - /* FALLTHROUGH */ case MDOC_Op: - /* FALLTHROUGH */ case MDOC_Bo: - /* FALLTHROUGH */ case MDOC_Bq: term_word(p, "["); break; case MDOC_Do: - /* FALLTHROUGH */ case MDOC_Dq: term_word(p, "\\(Lq"); break; case MDOC_En: if (NULL == n->norm->Es || NULL == n->norm->Es->child) - return(1); + return 1; term_word(p, n->norm->Es->child->string); break; case MDOC_Po: - /* FALLTHROUGH */ case MDOC_Pq: term_word(p, "("); break; case MDOC__T: - /* FALLTHROUGH */ case MDOC_Qo: - /* FALLTHROUGH */ case MDOC_Qq: term_word(p, "\""); break; case MDOC_Ql: - /* FALLTHROUGH */ case MDOC_So: - /* FALLTHROUGH */ case MDOC_Sq: term_word(p, "\\(oq"); break; default: abort(); - /* NOTREACHED */ } p->flags |= TERMP_NOSPACE; - return(1); + return 1; } static void termp_quote_post(DECL_ARGS) { - if (n->type != MDOC_BODY && n->type != MDOC_ELEM) + if (n->type != ROFFT_BODY && n->type != ROFFT_ELEM) return; p->flags |= TERMP_NOSPACE; switch (n->tok) { case MDOC_Ao: - /* FALLTHROUGH */ case MDOC_Aq: - term_word(p, n->nchild == 1 && + term_word(p, n->child != NULL && n->child->next == NULL && n->child->tok == MDOC_Mt ? ">" : "\\(ra"); break; case MDOC_Bro: - /* FALLTHROUGH */ case MDOC_Brq: term_word(p, "}"); break; case MDOC_Oo: - /* FALLTHROUGH */ case MDOC_Op: - /* FALLTHROUGH */ case MDOC_Bo: - /* FALLTHROUGH */ case MDOC_Bq: term_word(p, "]"); break; case MDOC_Do: - /* FALLTHROUGH */ case MDOC_Dq: term_word(p, "\\(Rq"); break; @@ -1958,27 +1922,21 @@ termp_quote_post(DECL_ARGS) term_word(p, n->norm->Es->child->next->string); break; case MDOC_Po: - /* FALLTHROUGH */ case MDOC_Pq: term_word(p, ")"); break; case MDOC__T: - /* FALLTHROUGH */ case MDOC_Qo: - /* FALLTHROUGH */ case MDOC_Qq: term_word(p, "\""); break; case MDOC_Ql: - /* FALLTHROUGH */ case MDOC_So: - /* FALLTHROUGH */ case MDOC_Sq: term_word(p, "\\(cq"); break; default: abort(); - /* NOTREACHED */ } } @@ -1986,8 +1944,8 @@ static int termp_eo_pre(DECL_ARGS) { - if (n->type != MDOC_BODY) - return(1); + if (n->type != ROFFT_BODY) + return 1; if (n->end == ENDBODY_NOT && n->parent->head->child == NULL && @@ -1999,7 +1957,7 @@ termp_eo_pre(DECL_ARGS) (n->parent->tail != NULL && n->parent->tail->child != NULL))) p->flags |= TERMP_NOSPACE; - return(1); + return 1; } static void @@ -2007,7 +1965,7 @@ termp_eo_post(DECL_ARGS) { int body, tail; - if (n->type != MDOC_BODY) + if (n->type != ROFFT_BODY) return; if (n->end != ENDBODY_NOT) { @@ -2034,10 +1992,10 @@ termp_fo_pre(DECL_ARGS) pretty = MDOC_SYNPRETTY & n->flags; - if (MDOC_BLOCK == n->type) { + if (n->type == ROFFT_BLOCK) { synopsis_pre(p, n); - return(1); - } else if (MDOC_BODY == n->type) { + return 1; + } else if (n->type == ROFFT_BODY) { if (pretty) { rmargin = p->rmargin; p->rmargin = p->offset + term_len(p, 4); @@ -2054,25 +2012,25 @@ termp_fo_pre(DECL_ARGS) p->offset = p->rmargin; p->rmargin = rmargin; } - return(1); + return 1; } if (NULL == n->child) - return(0); + return 0; /* XXX: we drop non-initial arguments as per groff. */ assert(n->child->string); term_fontpush(p, TERMFONT_BOLD); term_word(p, n->child->string); - return(0); + return 0; } static void termp_fo_post(DECL_ARGS) { - if (MDOC_BODY != n->type) + if (n->type != ROFFT_BODY) return; p->flags |= TERMP_NOSPACE; @@ -2089,10 +2047,10 @@ static int termp_bf_pre(DECL_ARGS) { - if (MDOC_HEAD == n->type) - return(0); - else if (MDOC_BODY != n->type) - return(1); + if (n->type == ROFFT_HEAD) + return 0; + else if (n->type != ROFFT_BODY) + return 1; if (FONT_Em == n->norm->Bf.font) term_fontpush(p, TERMFONT_UNDER); @@ -2101,7 +2059,7 @@ termp_bf_pre(DECL_ARGS) else term_fontpush(p, TERMFONT_NONE); - return(1); + return 1; } static int @@ -2118,7 +2076,7 @@ termp_sm_pre(DECL_ARGS) if (p->col && ! (TERMP_NONOSPACE & p->flags)) p->flags &= ~TERMP_NOSPACE; - return(0); + return 0; } static int @@ -2128,7 +2086,7 @@ termp_ap_pre(DECL_ARGS) p->flags |= TERMP_NOSPACE; term_word(p, "'"); p->flags |= TERMP_NOSPACE; - return(1); + return 1; } static void @@ -2163,16 +2121,16 @@ termp_li_pre(DECL_ARGS) { term_fontpush(p, TERMFONT_NONE); - return(1); + return 1; } static int termp_lk_pre(DECL_ARGS) { - const struct mdoc_node *link, *descr; + const struct roff_node *link, *descr; if (NULL == (link = n->child)) - return(0); + return 0; if (NULL != (descr = link->next)) { term_fontpush(p, TERMFONT_UNDER); @@ -2189,7 +2147,7 @@ termp_lk_pre(DECL_ARGS) term_word(p, link->string); term_fontpop(p); - return(0); + return 0; } static int @@ -2197,27 +2155,26 @@ termp_bk_pre(DECL_ARGS) { switch (n->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: break; - case MDOC_HEAD: - return(0); - case MDOC_BODY: - if (n->parent->args || 0 == n->prev->nchild) + case ROFFT_HEAD: + return 0; + case ROFFT_BODY: + if (n->parent->args != NULL || n->prev->child == NULL) p->flags |= TERMP_PREKEEP; break; default: abort(); - /* NOTREACHED */ } - return(1); + return 1; } static void termp_bk_post(DECL_ARGS) { - if (MDOC_BODY == n->type) + if (n->type == ROFFT_BODY) p->flags &= ~(TERMP_KEEP | TERMP_PREKEEP); } @@ -2246,10 +2203,10 @@ termp__t_pre(DECL_ARGS) */ if (n->parent && MDOC_Rs == n->parent->tok && n->parent->norm->Rs.quote_T) - return(termp_quote_pre(p, pair, meta, n)); + return termp_quote_pre(p, pair, meta, n); term_fontpush(p, TERMFONT_UNDER); - return(1); + return 1; } static int @@ -2257,5 +2214,32 @@ termp_under_pre(DECL_ARGS) { term_fontpush(p, TERMFONT_UNDER); - return(1); + return 1; +} + +static int +termp_er_pre(DECL_ARGS) +{ + + if (n->sec == SEC_ERRORS && + (n->parent->tok == MDOC_It || + (n->parent->tok == MDOC_Bq && + n->parent->parent->parent->tok == MDOC_It))) + tag_put(n->child->string, 1, p->line); + return 1; +} + +static int +termp_tag_pre(DECL_ARGS) +{ + + if (n->child != NULL && + n->child->type == ROFFT_TEXT && + n->prev == NULL && + (n->parent->tok == MDOC_It || + (n->parent->tok == MDOC_Xo && + n->parent->parent->prev == NULL && + n->parent->parent->parent->tok == MDOC_It))) + tag_put(n->child->string, 1, p->line); + return 1; } diff --git a/usr/src/cmd/mandoc/mdoc_validate.c b/usr/src/cmd/mandoc/mdoc_validate.c index eb531e8289..e369349c8a 100644 --- a/usr/src/cmd/mandoc/mdoc_validate.c +++ b/usr/src/cmd/mandoc/mdoc_validate.c @@ -1,16 +1,16 @@ -/* $Id: mdoc_validate.c,v 1.283 2015/02/23 13:55:55 schwarze Exp $ */ +/* $Id: mdoc_validate.c,v 1.301 2016/01/08 17:48:09 schwarze Exp $ */ /* * Copyright (c) 2008-2012 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010 Joerg Sonnenberger <joerg@netbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -31,16 +31,17 @@ #include <string.h> #include <time.h> -#include "mdoc.h" -#include "mandoc.h" #include "mandoc_aux.h" -#include "libmdoc.h" +#include "mandoc.h" +#include "roff.h" +#include "mdoc.h" #include "libmandoc.h" +#include "roff_int.h" +#include "libmdoc.h" /* FIXME: .Bl -diag can't have non-text children in HEAD. */ -#define PRE_ARGS struct mdoc *mdoc, struct mdoc_node *n -#define POST_ARGS struct mdoc *mdoc +#define POST_ARGS struct roff_man *mdoc enum check_ineq { CHECK_LT, @@ -48,34 +49,30 @@ enum check_ineq { CHECK_EQ }; -typedef void (*v_pre)(PRE_ARGS); typedef void (*v_post)(POST_ARGS); -struct valids { - v_pre pre; - v_post post; -}; - -static void check_text(struct mdoc *, int, int, char *); -static void check_argv(struct mdoc *, - struct mdoc_node *, struct mdoc_argv *); -static void check_args(struct mdoc *, struct mdoc_node *); -static int child_an(const struct mdoc_node *); -static enum mdoc_sec a2sec(const char *); -static size_t macro2len(enum mdoct); +static void check_text(struct roff_man *, int, int, char *); +static void check_argv(struct roff_man *, + struct roff_node *, struct mdoc_argv *); +static void check_args(struct roff_man *, struct roff_node *); +static int child_an(const struct roff_node *); +static size_t macro2len(int); static void rewrite_macro2len(char **); static void post_an(POST_ARGS); +static void post_an_norm(POST_ARGS); static void post_at(POST_ARGS); +static void post_bd(POST_ARGS); static void post_bf(POST_ARGS); static void post_bk(POST_ARGS); static void post_bl(POST_ARGS); static void post_bl_block(POST_ARGS); static void post_bl_block_tag(POST_ARGS); static void post_bl_head(POST_ARGS); +static void post_bl_norm(POST_ARGS); static void post_bx(POST_ARGS); -static void post_d1(POST_ARGS); static void post_defaults(POST_ARGS); +static void post_display(POST_ARGS); static void post_dd(POST_ARGS); static void post_dt(POST_ARGS); static void post_en(POST_ARGS); @@ -90,12 +87,13 @@ static void post_hyph(POST_ARGS); static void post_ignpar(POST_ARGS); static void post_it(POST_ARGS); static void post_lb(POST_ARGS); -static void post_literal(POST_ARGS); static void post_nd(POST_ARGS); static void post_nm(POST_ARGS); static void post_ns(POST_ARGS); +static void post_obsolete(POST_ARGS); static void post_os(POST_ARGS); static void post_par(POST_ARGS); +static void post_prevpar(POST_ARGS); static void post_root(POST_ARGS); static void post_rs(POST_ARGS); static void post_sh(POST_ARGS); @@ -105,149 +103,137 @@ static void post_sh_see_also(POST_ARGS); static void post_sh_authors(POST_ARGS); static void post_sm(POST_ARGS); static void post_st(POST_ARGS); -static void post_vt(POST_ARGS); - -static void pre_an(PRE_ARGS); -static void pre_bd(PRE_ARGS); -static void pre_bl(PRE_ARGS); -static void pre_dd(PRE_ARGS); -static void pre_display(PRE_ARGS); -static void pre_dt(PRE_ARGS); -static void pre_literal(PRE_ARGS); -static void pre_obsolete(PRE_ARGS); -static void pre_os(PRE_ARGS); -static void pre_par(PRE_ARGS); -static void pre_std(PRE_ARGS); - -static const struct valids mdoc_valids[MDOC_MAX] = { - { NULL, NULL }, /* Ap */ - { pre_dd, post_dd }, /* Dd */ - { pre_dt, post_dt }, /* Dt */ - { pre_os, post_os }, /* Os */ - { NULL, post_sh }, /* Sh */ - { NULL, post_ignpar }, /* Ss */ - { pre_par, post_par }, /* Pp */ - { pre_display, post_d1 }, /* D1 */ - { pre_literal, post_literal }, /* Dl */ - { pre_bd, post_literal }, /* Bd */ - { NULL, NULL }, /* Ed */ - { pre_bl, post_bl }, /* Bl */ - { NULL, NULL }, /* El */ - { pre_par, post_it }, /* It */ - { NULL, NULL }, /* Ad */ - { pre_an, post_an }, /* An */ - { NULL, post_defaults }, /* Ar */ - { NULL, NULL }, /* Cd */ - { NULL, NULL }, /* Cm */ - { NULL, NULL }, /* Dv */ - { NULL, NULL }, /* Er */ - { NULL, NULL }, /* Ev */ - { pre_std, post_ex }, /* Ex */ - { NULL, post_fa }, /* Fa */ - { NULL, NULL }, /* Fd */ - { NULL, NULL }, /* Fl */ - { NULL, post_fn }, /* Fn */ - { NULL, NULL }, /* Ft */ - { NULL, NULL }, /* Ic */ - { NULL, NULL }, /* In */ - { NULL, post_defaults }, /* Li */ - { NULL, post_nd }, /* Nd */ - { NULL, post_nm }, /* Nm */ - { NULL, NULL }, /* Op */ - { pre_obsolete, NULL }, /* Ot */ - { NULL, post_defaults }, /* Pa */ - { pre_std, NULL }, /* Rv */ - { NULL, post_st }, /* St */ - { NULL, NULL }, /* Va */ - { NULL, post_vt }, /* Vt */ - { NULL, NULL }, /* Xr */ - { NULL, NULL }, /* %A */ - { NULL, post_hyph }, /* %B */ /* FIXME: can be used outside Rs/Re. */ - { NULL, NULL }, /* %D */ - { NULL, NULL }, /* %I */ - { NULL, NULL }, /* %J */ - { NULL, post_hyph }, /* %N */ - { NULL, post_hyph }, /* %O */ - { NULL, NULL }, /* %P */ - { NULL, post_hyph }, /* %R */ - { NULL, post_hyph }, /* %T */ /* FIXME: can be used outside Rs/Re. */ - { NULL, NULL }, /* %V */ - { NULL, NULL }, /* Ac */ - { NULL, NULL }, /* Ao */ - { NULL, NULL }, /* Aq */ - { NULL, post_at }, /* At */ - { NULL, NULL }, /* Bc */ - { NULL, post_bf }, /* Bf */ - { NULL, NULL }, /* Bo */ - { NULL, NULL }, /* Bq */ - { NULL, NULL }, /* Bsx */ - { NULL, post_bx }, /* Bx */ - { pre_obsolete, NULL }, /* Db */ - { NULL, NULL }, /* Dc */ - { NULL, NULL }, /* Do */ - { NULL, NULL }, /* Dq */ - { NULL, NULL }, /* Ec */ - { NULL, NULL }, /* Ef */ - { NULL, NULL }, /* Em */ - { NULL, NULL }, /* Eo */ - { NULL, NULL }, /* Fx */ - { NULL, NULL }, /* Ms */ - { NULL, NULL }, /* No */ - { NULL, post_ns }, /* Ns */ - { NULL, NULL }, /* Nx */ - { NULL, NULL }, /* Ox */ - { NULL, NULL }, /* Pc */ - { NULL, NULL }, /* Pf */ - { NULL, NULL }, /* Po */ - { NULL, NULL }, /* Pq */ - { NULL, NULL }, /* Qc */ - { NULL, NULL }, /* Ql */ - { NULL, NULL }, /* Qo */ - { NULL, NULL }, /* Qq */ - { NULL, NULL }, /* Re */ - { NULL, post_rs }, /* Rs */ - { NULL, NULL }, /* Sc */ - { NULL, NULL }, /* So */ - { NULL, NULL }, /* Sq */ - { NULL, post_sm }, /* Sm */ - { NULL, post_hyph }, /* Sx */ - { NULL, NULL }, /* Sy */ - { NULL, NULL }, /* Tn */ - { NULL, NULL }, /* Ux */ - { NULL, NULL }, /* Xc */ - { NULL, NULL }, /* Xo */ - { NULL, post_fo }, /* Fo */ - { NULL, NULL }, /* Fc */ - { NULL, NULL }, /* Oo */ - { NULL, NULL }, /* Oc */ - { NULL, post_bk }, /* Bk */ - { NULL, NULL }, /* Ek */ - { NULL, post_eoln }, /* Bt */ - { NULL, NULL }, /* Hf */ - { pre_obsolete, NULL }, /* Fr */ - { NULL, post_eoln }, /* Ud */ - { NULL, post_lb }, /* Lb */ - { pre_par, post_par }, /* Lp */ - { NULL, NULL }, /* Lk */ - { NULL, post_defaults }, /* Mt */ - { NULL, NULL }, /* Brq */ - { NULL, NULL }, /* Bro */ - { NULL, NULL }, /* Brc */ - { NULL, NULL }, /* %C */ - { pre_obsolete, post_es }, /* Es */ - { pre_obsolete, post_en }, /* En */ - { NULL, NULL }, /* Dx */ - { NULL, NULL }, /* %Q */ - { NULL, post_par }, /* br */ - { NULL, post_par }, /* sp */ - { NULL, NULL }, /* %U */ - { NULL, NULL }, /* Ta */ - { NULL, NULL }, /* ll */ +static void post_std(POST_ARGS); + +static v_post mdoc_valids[MDOC_MAX] = { + NULL, /* Ap */ + post_dd, /* Dd */ + post_dt, /* Dt */ + post_os, /* Os */ + post_sh, /* Sh */ + post_ignpar, /* Ss */ + post_par, /* Pp */ + post_display, /* D1 */ + post_display, /* Dl */ + post_display, /* Bd */ + NULL, /* Ed */ + post_bl, /* Bl */ + NULL, /* El */ + post_it, /* It */ + NULL, /* Ad */ + post_an, /* An */ + post_defaults, /* Ar */ + NULL, /* Cd */ + NULL, /* Cm */ + NULL, /* Dv */ + NULL, /* Er */ + NULL, /* Ev */ + post_ex, /* Ex */ + post_fa, /* Fa */ + NULL, /* Fd */ + NULL, /* Fl */ + post_fn, /* Fn */ + NULL, /* Ft */ + NULL, /* Ic */ + NULL, /* In */ + post_defaults, /* Li */ + post_nd, /* Nd */ + post_nm, /* Nm */ + NULL, /* Op */ + post_obsolete, /* Ot */ + post_defaults, /* Pa */ + post_std, /* Rv */ + post_st, /* St */ + NULL, /* Va */ + NULL, /* Vt */ + NULL, /* Xr */ + NULL, /* %A */ + post_hyph, /* %B */ /* FIXME: can be used outside Rs/Re. */ + NULL, /* %D */ + NULL, /* %I */ + NULL, /* %J */ + post_hyph, /* %N */ + post_hyph, /* %O */ + NULL, /* %P */ + post_hyph, /* %R */ + post_hyph, /* %T */ /* FIXME: can be used outside Rs/Re. */ + NULL, /* %V */ + NULL, /* Ac */ + NULL, /* Ao */ + NULL, /* Aq */ + post_at, /* At */ + NULL, /* Bc */ + post_bf, /* Bf */ + NULL, /* Bo */ + NULL, /* Bq */ + NULL, /* Bsx */ + post_bx, /* Bx */ + post_obsolete, /* Db */ + NULL, /* Dc */ + NULL, /* Do */ + NULL, /* Dq */ + NULL, /* Ec */ + NULL, /* Ef */ + NULL, /* Em */ + NULL, /* Eo */ + NULL, /* Fx */ + NULL, /* Ms */ + NULL, /* No */ + post_ns, /* Ns */ + NULL, /* Nx */ + NULL, /* Ox */ + NULL, /* Pc */ + NULL, /* Pf */ + NULL, /* Po */ + NULL, /* Pq */ + NULL, /* Qc */ + NULL, /* Ql */ + NULL, /* Qo */ + NULL, /* Qq */ + NULL, /* Re */ + post_rs, /* Rs */ + NULL, /* Sc */ + NULL, /* So */ + NULL, /* Sq */ + post_sm, /* Sm */ + post_hyph, /* Sx */ + NULL, /* Sy */ + NULL, /* Tn */ + NULL, /* Ux */ + NULL, /* Xc */ + NULL, /* Xo */ + post_fo, /* Fo */ + NULL, /* Fc */ + NULL, /* Oo */ + NULL, /* Oc */ + post_bk, /* Bk */ + NULL, /* Ek */ + post_eoln, /* Bt */ + NULL, /* Hf */ + post_obsolete, /* Fr */ + post_eoln, /* Ud */ + post_lb, /* Lb */ + post_par, /* Lp */ + NULL, /* Lk */ + post_defaults, /* Mt */ + NULL, /* Brq */ + NULL, /* Bro */ + NULL, /* Brc */ + NULL, /* %C */ + post_es, /* Es */ + post_en, /* En */ + NULL, /* Dx */ + NULL, /* %Q */ + post_par, /* br */ + post_par, /* sp */ + NULL, /* %U */ + NULL, /* Ta */ + NULL, /* ll */ }; #define RSORD_MAX 14 /* Number of `Rs' blocks. */ -static const enum mdoct rsord[RSORD_MAX] = { +static const int rsord[RSORD_MAX] = { MDOC__A, MDOC__T, MDOC__B, @@ -292,53 +278,36 @@ static const char * const secnames[SEC__MAX] = { void -mdoc_valid_pre(struct mdoc *mdoc, struct mdoc_node *n) +mdoc_node_validate(struct roff_man *mdoc) { - v_pre p; + struct roff_node *n; + v_post *p; + n = mdoc->last; + mdoc->last = mdoc->last->child; + while (mdoc->last != NULL) { + mdoc_node_validate(mdoc); + if (mdoc->last == n) + mdoc->last = mdoc->last->child; + else + mdoc->last = mdoc->last->next; + } + + mdoc->last = n; + mdoc->next = ROFF_NEXT_SIBLING; switch (n->type) { - case MDOC_TEXT: + case ROFFT_TEXT: if (n->sec != SEC_SYNOPSIS || n->parent->tok != MDOC_Fd) check_text(mdoc, n->line, n->pos, n->string); - /* FALLTHROUGH */ - case MDOC_TBL: - /* FALLTHROUGH */ - case MDOC_EQN: - /* FALLTHROUGH */ - case MDOC_ROOT: - return; - default: break; - } - - check_args(mdoc, n); - p = mdoc_valids[n->tok].pre; - if (*p) - (*p)(mdoc, n); -} - -void -mdoc_valid_post(struct mdoc *mdoc) -{ - struct mdoc_node *n; - v_post p; - - n = mdoc->last; - if (n->flags & MDOC_VALID) - return; - n->flags |= MDOC_VALID | MDOC_ENDED; - - switch (n->type) { - case MDOC_TEXT: - /* FALLTHROUGH */ - case MDOC_EQN: - /* FALLTHROUGH */ - case MDOC_TBL: + case ROFFT_EQN: + case ROFFT_TBL: break; - case MDOC_ROOT: + case ROFFT_ROOT: post_root(mdoc); break; default: + check_args(mdoc, mdoc->last); /* * Closing delimiters are not special at the @@ -353,15 +322,17 @@ mdoc_valid_post(struct mdoc *mdoc) /* Call the macro's postprocessor. */ - p = mdoc_valids[n->tok].post; + p = mdoc_valids + n->tok; if (*p) (*p)(mdoc); + if (mdoc->last == n) + mdoc_state(mdoc, n); break; } } static void -check_args(struct mdoc *mdoc, struct mdoc_node *n) +check_args(struct roff_man *mdoc, struct roff_node *n) { int i; @@ -374,7 +345,7 @@ check_args(struct mdoc *mdoc, struct mdoc_node *n) } static void -check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v) +check_argv(struct roff_man *mdoc, struct roff_node *n, struct mdoc_argv *v) { int i; @@ -383,7 +354,7 @@ check_argv(struct mdoc *mdoc, struct mdoc_node *n, struct mdoc_argv *v) } static void -check_text(struct mdoc *mdoc, int ln, int pos, char *p) +check_text(struct roff_man *mdoc, int ln, int pos, char *p) { char *cp; @@ -396,34 +367,16 @@ check_text(struct mdoc *mdoc, int ln, int pos, char *p) } static void -pre_display(PRE_ARGS) -{ - struct mdoc_node *node; - - if (MDOC_BLOCK != n->type) - return; - - for (node = mdoc->last->parent; node; node = node->parent) - if (MDOC_BLOCK == node->type) - if (MDOC_Bd == node->tok) - break; - - if (node) - mandoc_vmsg(MANDOCERR_BD_NEST, - mdoc->parse, n->line, n->pos, - "%s in Bd", mdoc_macronames[n->tok]); -} - -static void -pre_bl(PRE_ARGS) +post_bl_norm(POST_ARGS) { + struct roff_node *n; struct mdoc_argv *argv, *wa; int i; enum mdocargt mdoclt; enum mdoc_list lt; - if (n->type != MDOC_BLOCK) - return; + n = mdoc->last->parent; + n->norm->Bl.type = LIST__NONE; /* * First figure out which kind of list to use: bind ourselves to @@ -565,13 +518,9 @@ pre_bl(PRE_ARGS) n->line, n->pos, "Bl -tag"); break; case LIST_column: - /* FALLTHROUGH */ case LIST_diag: - /* FALLTHROUGH */ case LIST_ohang: - /* FALLTHROUGH */ case LIST_inset: - /* FALLTHROUGH */ case LIST_item: if (n->norm->Bl.width) mandoc_vmsg(MANDOCERR_BL_SKIPW, mdoc->parse, @@ -579,9 +528,7 @@ pre_bl(PRE_ARGS) mdoc_argnames[mdoclt]); break; case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_hyphen: if (NULL == n->norm->Bl.width) n->norm->Bl.width = "2n"; @@ -593,21 +540,17 @@ pre_bl(PRE_ARGS) default: break; } - pre_par(mdoc, n); } static void -pre_bd(PRE_ARGS) +post_bd(POST_ARGS) { + struct roff_node *n; struct mdoc_argv *argv; int i; enum mdoc_disp dt; - pre_literal(mdoc, n); - - if (n->type != MDOC_BLOCK) - return; - + n = mdoc->last; for (i = 0; n->args && i < (int)n->args->argc; i++) { argv = n->args->argv + i; dt = DISP__NONE; @@ -656,7 +599,6 @@ pre_bd(PRE_ARGS) break; default: abort(); - /* NOTREACHED */ } if (DISP__NONE == dt) continue; @@ -674,15 +616,16 @@ pre_bd(PRE_ARGS) n->line, n->pos, "Bd"); n->norm->Bd.type = DISP_ragged; } - pre_par(mdoc, n); } static void -pre_an(PRE_ARGS) +post_an_norm(POST_ARGS) { + struct roff_node *n; struct mdoc_argv *argv; size_t i; + n = mdoc->last; if (n->args == NULL) return; @@ -703,11 +646,13 @@ pre_an(PRE_ARGS) } static void -pre_std(PRE_ARGS) +post_std(POST_ARGS) { + struct roff_node *n; - if (n->args && 1 == n->args->argc) - if (MDOC_Std == n->args->argv[0].arg) + n = mdoc->last; + if (n->args && n->args->argc == 1) + if (n->args->argv[0].arg == MDOC_Std) return; mandoc_msg(MANDOCERR_ARG_STD, mdoc->parse, @@ -715,61 +660,20 @@ pre_std(PRE_ARGS) } static void -pre_obsolete(PRE_ARGS) +post_obsolete(POST_ARGS) { + struct roff_node *n; - if (MDOC_ELEM == n->type || MDOC_BLOCK == n->type) + n = mdoc->last; + if (n->type == ROFFT_ELEM || n->type == ROFFT_BLOCK) mandoc_msg(MANDOCERR_MACRO_OBS, mdoc->parse, n->line, n->pos, mdoc_macronames[n->tok]); } static void -pre_dt(PRE_ARGS) -{ - - if (mdoc->meta.title != NULL) - mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, - n->line, n->pos, "Dt"); - else if (mdoc->meta.os != NULL) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dt after Os"); -} - -static void -pre_os(PRE_ARGS) -{ - - if (mdoc->meta.os != NULL) - mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, - n->line, n->pos, "Os"); - else if (mdoc->flags & MDOC_PBODY) - mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, - n->line, n->pos, "Os"); -} - -static void -pre_dd(PRE_ARGS) -{ - - if (mdoc->meta.date != NULL) - mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, - n->line, n->pos, "Dd"); - else if (mdoc->flags & MDOC_PBODY) - mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, - n->line, n->pos, "Dd"); - else if (mdoc->meta.title != NULL) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dd after Dt"); - else if (mdoc->meta.os != NULL) - mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, - n->line, n->pos, "Dd after Os"); -} - -static void post_bf(POST_ARGS) { - struct mdoc_node *np, *nch; - enum mdocargt arg; + struct roff_node *np, *nch; /* * Unlike other data pointers, these are "housed" by the HEAD @@ -777,49 +681,53 @@ post_bf(POST_ARGS) */ np = mdoc->last; - if (MDOC_HEAD != np->type) + if (np->type != ROFFT_HEAD) return; - assert(MDOC_BLOCK == np->parent->type); - assert(MDOC_Bf == np->parent->tok); + assert(np->parent->type == ROFFT_BLOCK); + assert(np->parent->tok == MDOC_Bf); /* Check the number of arguments. */ nch = np->child; - if (NULL == np->parent->args) { - if (NULL == nch) { + if (np->parent->args == NULL) { + if (nch == NULL) { mandoc_msg(MANDOCERR_BF_NOFONT, mdoc->parse, np->line, np->pos, "Bf"); return; } nch = nch->next; } - if (NULL != nch) + if (nch != NULL) mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, nch->line, nch->pos, "Bf ... %s", nch->string); /* Extract argument into data. */ - if (np->parent->args) { - arg = np->parent->args->argv[0].arg; - if (MDOC_Emphasis == arg) + if (np->parent->args != NULL) { + switch (np->parent->args->argv[0].arg) { + case MDOC_Emphasis: np->norm->Bf.font = FONT_Em; - else if (MDOC_Literal == arg) + break; + case MDOC_Literal: np->norm->Bf.font = FONT_Li; - else if (MDOC_Symbolic == arg) + break; + case MDOC_Symbolic: np->norm->Bf.font = FONT_Sy; - else + break; + default: abort(); + } return; } /* Extract parameter into data. */ - if (0 == strcmp(np->child->string, "Em")) + if ( ! strcmp(np->child->string, "Em")) np->norm->Bf.font = FONT_Em; - else if (0 == strcmp(np->child->string, "Li")) + else if ( ! strcmp(np->child->string, "Li")) np->norm->Bf.font = FONT_Li; - else if (0 == strcmp(np->child->string, "Sy")) + else if ( ! strcmp(np->child->string, "Sy")) np->norm->Bf.font = FONT_Sy; else mandoc_vmsg(MANDOCERR_BF_BADFONT, mdoc->parse, @@ -830,12 +738,12 @@ post_bf(POST_ARGS) static void post_lb(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; const char *stdlibname; char *libname; n = mdoc->last->child; - assert(MDOC_TEXT == n->type); + assert(n->type == ROFFT_TEXT); if (NULL == (stdlibname = mdoc_a2lib(n->string))) mandoc_asprintf(&libname, @@ -850,10 +758,10 @@ post_lb(POST_ARGS) static void post_eoln(POST_ARGS) { - const struct mdoc_node *n; + const struct roff_node *n; n = mdoc->last; - if (n->child) + if (n->child != NULL) mandoc_vmsg(MANDOCERR_ARG_SKIP, mdoc->parse, n->line, n->pos, "%s %s", mdoc_macronames[n->tok], @@ -863,7 +771,7 @@ post_eoln(POST_ARGS) static void post_fname(POST_ARGS) { - const struct mdoc_node *n; + const struct roff_node *n; const char *cp; size_t pos; @@ -886,11 +794,11 @@ post_fn(POST_ARGS) static void post_fo(POST_ARGS) { - const struct mdoc_node *n; + const struct roff_node *n; n = mdoc->last; - if (n->type != MDOC_HEAD) + if (n->type != ROFFT_HEAD) return; if (n->child == NULL) { @@ -903,7 +811,7 @@ post_fo(POST_ARGS) n->child->next->line, n->child->next->pos, "Fo ... %s", n->child->next->string); while (n->child != n->last) - mdoc_node_delete(mdoc, n->last); + roff_node_delete(mdoc, n->last); } post_fname(mdoc); @@ -912,7 +820,7 @@ post_fo(POST_ARGS) static void post_fa(POST_ARGS) { - const struct mdoc_node *n; + const struct roff_node *n; const char *cp; for (n = mdoc->last->child; n != NULL; n = n->next) { @@ -931,31 +839,9 @@ post_fa(POST_ARGS) } static void -post_vt(POST_ARGS) -{ - const struct mdoc_node *n; - - /* - * The Vt macro comes in both ELEM and BLOCK form, both of which - * have different syntaxes (yet more context-sensitive - * behaviour). ELEM types must have a child, which is already - * guaranteed by the in_line parsing routine; BLOCK types, - * specifically the BODY, should only have TEXT children. - */ - - if (MDOC_BODY != mdoc->last->type) - return; - - for (n = mdoc->last->child; n; n = n->next) - if (MDOC_TEXT != n->type) - mandoc_msg(MANDOCERR_VT_CHILD, mdoc->parse, - n->line, n->pos, mdoc_macronames[n->tok]); -} - -static void post_nm(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; n = mdoc->last; @@ -964,12 +850,12 @@ post_nm(POST_ARGS) n->last->tok == MDOC_Lp)) mdoc_node_relink(mdoc, n->last); - if (NULL != mdoc->meta.name) + if (mdoc->meta.name != NULL) return; - mdoc_deroff(&mdoc->meta.name, n); + deroff(&mdoc->meta.name, n); - if (NULL == mdoc->meta.name) + if (mdoc->meta.name == NULL) mandoc_msg(MANDOCERR_NM_NONAME, mdoc->parse, n->line, n->pos, "Nm"); } @@ -977,11 +863,11 @@ post_nm(POST_ARGS) static void post_nd(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; n = mdoc->last; - if (n->type != MDOC_BODY) + if (n->type != ROFFT_BODY) return; if (n->child == NULL) @@ -992,48 +878,54 @@ post_nd(POST_ARGS) } static void -post_d1(POST_ARGS) +post_display(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n, *np; n = mdoc->last; - - if (n->type != MDOC_BODY) - return; - - if (n->child == NULL) - mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, - n->line, n->pos, "D1"); - - post_hyph(mdoc); -} - -static void -post_literal(POST_ARGS) -{ - struct mdoc_node *n; - - n = mdoc->last; - - if (n->type != MDOC_BODY) - return; - - if (n->child == NULL) - mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, - n->line, n->pos, mdoc_macronames[n->tok]); - - if (n->tok == MDOC_Bd && - n->norm->Bd.type != DISP_literal && - n->norm->Bd.type != DISP_unfilled) - return; - - mdoc->flags &= ~MDOC_LITERAL; + switch (n->type) { + case ROFFT_BODY: + if (n->end != ENDBODY_NOT) + break; + if (n->child == NULL) + mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, + n->line, n->pos, mdoc_macronames[n->tok]); + else if (n->tok == MDOC_D1) + post_hyph(mdoc); + break; + case ROFFT_BLOCK: + if (n->tok == MDOC_Bd) { + if (n->args == NULL) { + mandoc_msg(MANDOCERR_BD_NOARG, + mdoc->parse, n->line, n->pos, "Bd"); + mdoc->next = ROFF_NEXT_SIBLING; + while (n->body->child != NULL) + mdoc_node_relink(mdoc, + n->body->child); + roff_node_delete(mdoc, n); + break; + } + post_bd(mdoc); + post_prevpar(mdoc); + } + for (np = n->parent; np != NULL; np = np->parent) { + if (np->type == ROFFT_BLOCK && np->tok == MDOC_Bd) { + mandoc_vmsg(MANDOCERR_BD_NEST, + mdoc->parse, n->line, n->pos, + "%s in Bd", mdoc_macronames[n->tok]); + break; + } + } + break; + default: + break; + } } static void post_defaults(POST_ARGS) { - struct mdoc_node *nn; + struct roff_node *nn; /* * The `Ar' defaults to "file ..." if no value is provided as an @@ -1041,25 +933,24 @@ post_defaults(POST_ARGS) * gets an empty string. */ - if (mdoc->last->child) + if (mdoc->last->child != NULL) return; nn = mdoc->last; - mdoc->next = MDOC_NEXT_CHILD; switch (nn->tok) { case MDOC_Ar: - mdoc_word_alloc(mdoc, nn->line, nn->pos, "file"); - mdoc_word_alloc(mdoc, nn->line, nn->pos, "..."); + mdoc->next = ROFF_NEXT_CHILD; + roff_word_alloc(mdoc, nn->line, nn->pos, "file"); + roff_word_alloc(mdoc, nn->line, nn->pos, "..."); break; case MDOC_Pa: - /* FALLTHROUGH */ case MDOC_Mt: - mdoc_word_alloc(mdoc, nn->line, nn->pos, "~"); + mdoc->next = ROFF_NEXT_CHILD; + roff_word_alloc(mdoc, nn->line, nn->pos, "~"); break; default: abort(); - /* NOTREACHED */ } mdoc->last = nn; } @@ -1067,14 +958,14 @@ post_defaults(POST_ARGS) static void post_at(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; const char *std_att; char *att; n = mdoc->last; if (n->child == NULL) { - mdoc->next = MDOC_NEXT_CHILD; - mdoc_word_alloc(mdoc, n->line, n->pos, "AT&T UNIX"); + mdoc->next = ROFF_NEXT_CHILD; + roff_word_alloc(mdoc, n->line, n->pos, "AT&T UNIX"); mdoc->last = n; return; } @@ -1086,8 +977,8 @@ post_at(POST_ARGS) */ n = n->child; - assert(MDOC_TEXT == n->type); - if (NULL == (std_att = mdoc_a2att(n->string))) { + assert(n->type == ROFFT_TEXT); + if ((std_att = mdoc_a2att(n->string)) == NULL) { mandoc_vmsg(MANDOCERR_AT_BAD, mdoc->parse, n->line, n->pos, "At %s", n->string); mandoc_asprintf(&att, "AT&T UNIX %s", n->string); @@ -1101,7 +992,9 @@ post_at(POST_ARGS) static void post_an(POST_ARGS) { - struct mdoc_node *np, *nch; + struct roff_node *np, *nch; + + post_an_norm(mdoc); np = mdoc->last; nch = np->child; @@ -1118,7 +1011,8 @@ static void post_en(POST_ARGS) { - if (MDOC_BLOCK == mdoc->last->type) + post_obsolete(mdoc); + if (mdoc->last->type == ROFFT_BLOCK) mdoc->last->norm->Es = mdoc->last_es; } @@ -1126,18 +1020,21 @@ static void post_es(POST_ARGS) { + post_obsolete(mdoc); mdoc->last_es = mdoc->last; } static void post_it(POST_ARGS) { + struct roff_node *nbl, *nit, *nch; int i, cols; enum mdoc_list lt; - struct mdoc_node *nbl, *nit, *nch; + + post_prevpar(mdoc); nit = mdoc->last; - if (nit->type != MDOC_BLOCK) + if (nit->type != ROFFT_BLOCK) return; nbl = nit->parent->parent; @@ -1145,13 +1042,9 @@ post_it(POST_ARGS) switch (lt) { case LIST_tag: - /* FALLTHROUGH */ case LIST_hang: - /* FALLTHROUGH */ case LIST_ohang: - /* FALLTHROUGH */ case LIST_inset: - /* FALLTHROUGH */ case LIST_diag: if (nit->head->child == NULL) mandoc_vmsg(MANDOCERR_IT_NOHEAD, @@ -1160,11 +1053,8 @@ post_it(POST_ARGS) mdoc_argnames[nbl->args->argv[0].arg]); break; case LIST_bullet: - /* FALLTHROUGH */ case LIST_dash: - /* FALLTHROUGH */ case LIST_enum: - /* FALLTHROUGH */ case LIST_hyphen: if (nit->body == NULL || nit->body->child == NULL) mandoc_vmsg(MANDOCERR_IT_NOBODY, @@ -1183,8 +1073,9 @@ post_it(POST_ARGS) assert(nit->head->child == NULL); - for (i = 0, nch = nit->child; nch; nch = nch->next) - if (nch->type == MDOC_BODY) + i = 0; + for (nch = nit->child; nch != NULL; nch = nch->next) + if (nch->type == ROFFT_BODY) i++; if (i < cols || i > cols + 1) @@ -1200,7 +1091,9 @@ post_it(POST_ARGS) static void post_bl_block(POST_ARGS) { - struct mdoc_node *n, *ni, *nc; + struct roff_node *n, *ni, *nc; + + post_prevpar(mdoc); /* * These are fairly complicated, so we've broken them into two @@ -1212,40 +1105,38 @@ post_bl_block(POST_ARGS) n = mdoc->last; - if (LIST_tag == n->norm->Bl.type && - NULL == n->norm->Bl.width) { + if (n->norm->Bl.type == LIST_tag && + n->norm->Bl.width == NULL) { post_bl_block_tag(mdoc); - assert(n->norm->Bl.width); + assert(n->norm->Bl.width != NULL); } - for (ni = n->body->child; ni; ni = ni->next) { - if (NULL == ni->body) + for (ni = n->body->child; ni != NULL; ni = ni->next) { + if (ni->body == NULL) continue; nc = ni->body->last; - while (NULL != nc) { + while (nc != NULL) { switch (nc->tok) { case MDOC_Pp: - /* FALLTHROUGH */ case MDOC_Lp: - /* FALLTHROUGH */ case MDOC_br: break; default: nc = NULL; continue; } - if (NULL == ni->next) { + if (ni->next == NULL) { mandoc_msg(MANDOCERR_PAR_MOVE, mdoc->parse, nc->line, nc->pos, mdoc_macronames[nc->tok]); mdoc_node_relink(mdoc, nc); - } else if (0 == n->norm->Bl.comp && - LIST_column != n->norm->Bl.type) { + } else if (n->norm->Bl.comp == 0 && + n->norm->Bl.type != LIST_column) { mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, nc->line, nc->pos, "%s before It", mdoc_macronames[nc->tok]); - mdoc_node_delete(mdoc, nc); + roff_node_delete(mdoc, nc); } else break; nc = ni->body->last; @@ -1261,13 +1152,13 @@ void rewrite_macro2len(char **arg) { size_t width; - enum mdoct tok; + int tok; if (*arg == NULL) return; else if ( ! strcmp(*arg, "Ds")) width = 6; - else if ((tok = mdoc_hash_find(*arg)) == MDOC_MAX) + else if ((tok = mdoc_hash_find(*arg)) == TOKEN_NONE) return; else width = macro2len(tok); @@ -1279,7 +1170,7 @@ rewrite_macro2len(char **arg) static void post_bl_block_tag(POST_ARGS) { - struct mdoc_node *n, *nn; + struct roff_node *n, *nn; size_t sz, ssz; int i; char buf[24]; @@ -1294,17 +1185,17 @@ post_bl_block_tag(POST_ARGS) sz = 10; n = mdoc->last; - for (nn = n->body->child; nn; nn = nn->next) { - if (MDOC_It != nn->tok) + for (nn = n->body->child; nn != NULL; nn = nn->next) { + if (nn->tok != MDOC_It) continue; - assert(MDOC_BLOCK == nn->type); + assert(nn->type == ROFFT_BLOCK); nn = nn->head->child; if (nn == NULL) break; - if (MDOC_TEXT == nn->type) { + if (nn->type == ROFFT_TEXT) { sz = strlen(nn->string) + 1; break; } @@ -1324,7 +1215,7 @@ post_bl_block_tag(POST_ARGS) * We're guaranteed that a MDOC_Width doesn't already exist. */ - assert(n->args); + assert(n->args != NULL); i = (int)(n->args->argc)++; n->args->argv = mandoc_reallocarray(n->args->argv, @@ -1344,19 +1235,20 @@ post_bl_block_tag(POST_ARGS) static void post_bl_head(POST_ARGS) { - struct mdoc_node *nbl, *nh, *nch, *nnext; + struct roff_node *nbl, *nh, *nch, *nnext; struct mdoc_argv *argv; int i, j; - nh = mdoc->last; + post_bl_norm(mdoc); + nh = mdoc->last; if (nh->norm->Bl.type != LIST_column) { if ((nch = nh->child) == NULL) return; mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, nch->line, nch->pos, "Bl ... %s", nch->string); while (nch != NULL) { - mdoc_node_delete(mdoc, nch); + roff_node_delete(mdoc, nch); nch = nh->child; } return; @@ -1386,7 +1278,8 @@ post_bl_head(POST_ARGS) argv = nbl->args->argv + j; i = argv->sz; - argv->sz += nh->nchild; + for (nch = nh->child; nch != NULL; nch = nch->next) + argv->sz++; argv->value = mandoc_reallocarray(argv->value, argv->sz, sizeof(char *)); @@ -1397,32 +1290,33 @@ post_bl_head(POST_ARGS) argv->value[i++] = nch->string; nch->string = NULL; nnext = nch->next; - mdoc_node_delete(NULL, nch); + roff_node_delete(NULL, nch); } - nh->nchild = 0; nh->child = NULL; } static void post_bl(POST_ARGS) { - struct mdoc_node *nparent, *nprev; /* of the Bl block */ - struct mdoc_node *nblock, *nbody; /* of the Bl */ - struct mdoc_node *nchild, *nnext; /* of the Bl body */ + struct roff_node *nparent, *nprev; /* of the Bl block */ + struct roff_node *nblock, *nbody; /* of the Bl */ + struct roff_node *nchild, *nnext; /* of the Bl body */ nbody = mdoc->last; switch (nbody->type) { - case MDOC_BLOCK: + case ROFFT_BLOCK: post_bl_block(mdoc); return; - case MDOC_HEAD: + case ROFFT_HEAD: post_bl_head(mdoc); return; - case MDOC_BODY: + case ROFFT_BODY: break; default: return; } + if (nbody->end != ENDBODY_NOT) + return; nchild = nbody->child; if (nchild == NULL) { @@ -1457,15 +1351,12 @@ post_bl(POST_ARGS) * Unlink this child. */ - assert(NULL == nchild->prev); - if (0 == --nbody->nchild) { - nbody->child = NULL; + assert(nchild->prev == NULL); + nbody->child = nnext; + if (nnext == NULL) nbody->last = NULL; - assert(NULL == nnext); - } else { - nbody->child = nnext; + else nnext->prev = NULL; - } /* * Relink this child. @@ -1476,8 +1367,7 @@ post_bl(POST_ARGS) nchild->next = nblock; nblock->prev = nchild; - nparent->nchild++; - if (NULL == nprev) + if (nprev == NULL) nparent->child = nchild; else nprev->next = nchild; @@ -1489,21 +1379,21 @@ post_bl(POST_ARGS) static void post_bk(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; n = mdoc->last; - if (n->type == MDOC_BLOCK && n->body->child == NULL) { + if (n->type == ROFFT_BLOCK && n->body->child == NULL) { mandoc_msg(MANDOCERR_BLK_EMPTY, mdoc->parse, n->line, n->pos, "Bk"); - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } } static void -post_sm(struct mdoc *mdoc) +post_sm(POST_ARGS) { - struct mdoc_node *nch; + struct roff_node *nch; nch = mdoc->last->child; @@ -1512,7 +1402,7 @@ post_sm(struct mdoc *mdoc) return; } - assert(nch->type == MDOC_TEXT); + assert(nch->type == ROFFT_TEXT); if ( ! strcmp(nch->string, "on")) { mdoc->flags &= ~MDOC_SMOFF; @@ -1533,7 +1423,7 @@ post_sm(struct mdoc *mdoc) static void post_root(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; /* Add missing prologue data. */ @@ -1560,7 +1450,8 @@ post_root(POST_ARGS) /* Check that we begin with a proper `Sh'. */ n = mdoc->first->child; - while (n != NULL && mdoc_macros[n->tok].flags & MDOC_PROLOGUE) + while (n != NULL && n->tok != TOKEN_NONE && + mdoc_macros[n->tok].flags & MDOC_PROLOGUE) n = n->next; if (n == NULL) @@ -1573,18 +1464,18 @@ post_root(POST_ARGS) static void post_st(POST_ARGS) { - struct mdoc_node *n, *nch; + struct roff_node *n, *nch; const char *p; n = mdoc->last; nch = n->child; - assert(MDOC_TEXT == nch->type); + assert(nch->type == ROFFT_TEXT); - if (NULL == (p = mdoc_a2st(nch->string))) { + if ((p = mdoc_a2st(nch->string)) == NULL) { mandoc_vmsg(MANDOCERR_ST_BAD, mdoc->parse, nch->line, nch->pos, "St %s", nch->string); - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } else { free(nch->string); nch->string = mandoc_strdup(p); @@ -1594,12 +1485,12 @@ post_st(POST_ARGS) static void post_rs(POST_ARGS) { - struct mdoc_node *np, *nch, *next, *prev; + struct roff_node *np, *nch, *next, *prev; int i, j; np = mdoc->last; - if (np->type != MDOC_BODY) + if (np->type != ROFFT_BODY) return; if (np->child == NULL) { @@ -1631,7 +1522,7 @@ post_rs(POST_ARGS) /* * Remove this child from the chain. This somewhat - * repeats mdoc_node_unlink(), but since we're + * repeats roff_node_unlink(), but since we're * just re-ordering, there's no need for the * full unlink process. */ @@ -1688,11 +1579,11 @@ post_rs(POST_ARGS) static void post_hyph(POST_ARGS) { - struct mdoc_node *nch; + struct roff_node *nch; char *cp; for (nch = mdoc->last->child; nch != NULL; nch = nch->next) { - if (nch->type != MDOC_TEXT) + if (nch->type != ROFFT_TEXT) continue; cp = nch->string; if (*cp == '\0') @@ -1709,7 +1600,7 @@ static void post_ns(POST_ARGS) { - if (MDOC_LINE & mdoc->last->flags) + if (mdoc->last->flags & MDOC_LINE) mandoc_msg(MANDOCERR_NS_SKIP, mdoc->parse, mdoc->last->line, mdoc->last->pos, NULL); } @@ -1721,10 +1612,10 @@ post_sh(POST_ARGS) post_ignpar(mdoc); switch (mdoc->last->type) { - case MDOC_HEAD: + case ROFFT_HEAD: post_sh_head(mdoc); break; - case MDOC_BODY: + case ROFFT_BODY: switch (mdoc->lastsec) { case SEC_NAME: post_sh_name(mdoc); @@ -1747,7 +1638,7 @@ post_sh(POST_ARGS) static void post_sh_name(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; int hasnm, hasnd; hasnm = hasnd = 0; @@ -1763,7 +1654,7 @@ post_sh_name(POST_ARGS) mandoc_msg(MANDOCERR_NAMESEC_ND, mdoc->parse, n->line, n->pos, NULL); break; - case MDOC_MAX: + case TOKEN_NONE: if (hasnm) break; /* FALLTHROUGH */ @@ -1785,7 +1676,7 @@ post_sh_name(POST_ARGS) static void post_sh_see_also(POST_ARGS) { - const struct mdoc_node *n; + const struct roff_node *n; const char *name, *sec; const char *lastname, *lastsec, *lastpunct; int cmp; @@ -1793,7 +1684,9 @@ post_sh_see_also(POST_ARGS) n = mdoc->last->child; lastname = lastsec = lastpunct = NULL; while (n != NULL) { - if (n->tok != MDOC_Xr || n->nchild < 2) + if (n->tok != MDOC_Xr || + n->child == NULL || + n->child->next == NULL) break; /* Process one .Xr node. */ @@ -1830,7 +1723,7 @@ post_sh_see_also(POST_ARGS) lastpunct = "none"; continue; } - if (n->type != MDOC_TEXT) + if (n->type != ROFFT_TEXT) break; for (name = n->string; *name != '\0'; name++) if (isalpha((const unsigned char)*name)) @@ -1845,13 +1738,13 @@ post_sh_see_also(POST_ARGS) } static int -child_an(const struct mdoc_node *n) +child_an(const struct roff_node *n) { for (n = n->child; n != NULL; n = n->next) - if ((n->tok == MDOC_An && n->nchild) || child_an(n)) - return(1); - return(0); + if ((n->tok == MDOC_An && n->child != NULL) || child_an(n)) + return 1; + return 0; } static void @@ -1866,10 +1759,8 @@ post_sh_authors(POST_ARGS) static void post_sh_head(POST_ARGS) { - struct mdoc_node *n; const char *goodsec; - char *secname; - enum mdoc_sec sec; + enum roff_sec sec; /* * Process a new section. Sections are either "named" or @@ -1878,21 +1769,18 @@ post_sh_head(POST_ARGS) * manual sections. */ - secname = NULL; - sec = SEC_CUSTOM; - mdoc_deroff(&secname, mdoc->last); - sec = NULL == secname ? SEC_CUSTOM : a2sec(secname); + sec = mdoc->last->sec; /* The NAME should be first. */ if (SEC_NAME != sec && SEC_NONE == mdoc->lastnamed) mandoc_vmsg(MANDOCERR_NAMESEC_FIRST, mdoc->parse, mdoc->last->line, mdoc->last->pos, - "Sh %s", secname); + "Sh %s", secnames[sec]); /* The SYNOPSIS gets special attention in other areas. */ - if (SEC_SYNOPSIS == sec) { + if (sec == SEC_SYNOPSIS) { roff_setreg(mdoc->roff, "nS", 1, '='); mdoc->flags |= MDOC_SYNOPSIS; } else { @@ -1904,26 +1792,10 @@ post_sh_head(POST_ARGS) mdoc->lastsec = sec; - /* - * Set the section attribute for the current HEAD, for its - * parent BLOCK, and for the HEAD children; the latter can - * only be TEXT nodes, so no recursion is needed. - * For other blocks and elements, including .Sh BODY, this is - * done when allocating the node data structures, but for .Sh - * BLOCK and HEAD, the section is still unknown at that time. - */ - - mdoc->last->parent->sec = sec; - mdoc->last->sec = sec; - for (n = mdoc->last->child; n; n = n->next) - n->sec = sec; - /* We don't care about custom sections after this. */ - if (SEC_CUSTOM == sec) { - free(secname); + if (sec == SEC_CUSTOM) return; - } /* * Check whether our non-custom section is being repeated or is @@ -1933,12 +1805,12 @@ post_sh_head(POST_ARGS) if (sec == mdoc->lastnamed) mandoc_vmsg(MANDOCERR_SEC_REP, mdoc->parse, mdoc->last->line, mdoc->last->pos, - "Sh %s", secname); + "Sh %s", secnames[sec]); if (sec < mdoc->lastnamed) mandoc_vmsg(MANDOCERR_SEC_ORDER, mdoc->parse, mdoc->last->line, mdoc->last->pos, - "Sh %s", secname); + "Sh %s", secnames[sec]); /* Mark the last named section. */ @@ -1946,10 +1818,8 @@ post_sh_head(POST_ARGS) /* Check particular section/manual conventions. */ - if (mdoc->meta.msec == NULL) { - free(secname); + if (mdoc->meta.msec == NULL) return; - } goodsec = NULL; switch (sec) { @@ -1959,7 +1829,6 @@ post_sh_head(POST_ARGS) goodsec = "2, 3, 4, 9"; /* FALLTHROUGH */ case SEC_RETURN_VALUES: - /* FALLTHROUGH */ case SEC_LIBRARY: if (*mdoc->meta.msec == '2') break; @@ -1975,55 +1844,56 @@ post_sh_head(POST_ARGS) goodsec = "9"; mandoc_vmsg(MANDOCERR_SEC_MSEC, mdoc->parse, mdoc->last->line, mdoc->last->pos, - "Sh %s for %s only", secname, goodsec); + "Sh %s for %s only", secnames[sec], goodsec); break; default: break; } - free(secname); } static void post_ignpar(POST_ARGS) { - struct mdoc_node *np; + struct roff_node *np; switch (mdoc->last->type) { - case MDOC_HEAD: + case ROFFT_HEAD: post_hyph(mdoc); return; - case MDOC_BODY: + case ROFFT_BODY: break; default: return; } - if (NULL != (np = mdoc->last->child)) - if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { + if ((np = mdoc->last->child) != NULL) + if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) { mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, np->line, np->pos, "%s after %s", mdoc_macronames[np->tok], mdoc_macronames[mdoc->last->tok]); - mdoc_node_delete(mdoc, np); + roff_node_delete(mdoc, np); } - if (NULL != (np = mdoc->last->last)) - if (MDOC_Pp == np->tok || MDOC_Lp == np->tok) { + if ((np = mdoc->last->last) != NULL) + if (np->tok == MDOC_Pp || np->tok == MDOC_Lp) { mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, np->line, np->pos, "%s at the end of %s", mdoc_macronames[np->tok], mdoc_macronames[mdoc->last->tok]); - mdoc_node_delete(mdoc, np); + roff_node_delete(mdoc, np); } } static void -pre_par(PRE_ARGS) +post_prevpar(POST_ARGS) { + struct roff_node *n; - if (NULL == mdoc->last) + n = mdoc->last; + if (NULL == n->prev) return; - if (MDOC_ELEM != n->type && MDOC_BLOCK != n->type) + if (n->type != ROFFT_ELEM && n->type != ROFFT_BLOCK) return; /* @@ -2031,33 +1901,35 @@ pre_par(PRE_ARGS) * block: `Lp', `Pp', or non-compact `Bd' or `Bl'. */ - if (MDOC_Pp != mdoc->last->tok && - MDOC_Lp != mdoc->last->tok && - MDOC_br != mdoc->last->tok) + if (n->prev->tok != MDOC_Pp && + n->prev->tok != MDOC_Lp && + n->prev->tok != MDOC_br) return; - if (MDOC_Bl == n->tok && n->norm->Bl.comp) + if (n->tok == MDOC_Bl && n->norm->Bl.comp) return; - if (MDOC_Bd == n->tok && n->norm->Bd.comp) + if (n->tok == MDOC_Bd && n->norm->Bd.comp) return; - if (MDOC_It == n->tok && n->parent->norm->Bl.comp) + if (n->tok == MDOC_It && n->parent->norm->Bl.comp) return; mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, - mdoc->last->line, mdoc->last->pos, - "%s before %s", mdoc_macronames[mdoc->last->tok], + n->prev->line, n->prev->pos, + "%s before %s", mdoc_macronames[n->prev->tok], mdoc_macronames[n->tok]); - mdoc_node_delete(mdoc, mdoc->last); + roff_node_delete(mdoc, n->prev); } static void post_par(POST_ARGS) { - struct mdoc_node *np; + struct roff_node *np; np = mdoc->last; + if (np->tok != MDOC_br && np->tok != MDOC_sp) + post_prevpar(mdoc); if (np->tok == MDOC_sp) { - if (np->nchild > 1) + if (np->child != NULL && np->child->next != NULL) mandoc_vmsg(MANDOCERR_ARG_EXCESS, mdoc->parse, np->child->next->line, np->child->next->pos, "sp ... %s", np->child->next->string); @@ -2066,70 +1938,51 @@ post_par(POST_ARGS) mdoc->parse, np->line, np->pos, "%s %s", mdoc_macronames[np->tok], np->child->string); - if (NULL == (np = mdoc->last->prev)) { + if ((np = mdoc->last->prev) == NULL) { np = mdoc->last->parent; - if (MDOC_Sh != np->tok && MDOC_Ss != np->tok) + if (np->tok != MDOC_Sh && np->tok != MDOC_Ss) return; - } else if (MDOC_Pp != np->tok && MDOC_Lp != np->tok && - (MDOC_br != mdoc->last->tok || - (MDOC_sp != np->tok && MDOC_br != np->tok))) + } else if (np->tok != MDOC_Pp && np->tok != MDOC_Lp && + (mdoc->last->tok != MDOC_br || + (np->tok != MDOC_sp && np->tok != MDOC_br))) return; mandoc_vmsg(MANDOCERR_PAR_SKIP, mdoc->parse, mdoc->last->line, mdoc->last->pos, "%s after %s", mdoc_macronames[mdoc->last->tok], mdoc_macronames[np->tok]); - mdoc_node_delete(mdoc, mdoc->last); -} - -static void -pre_literal(PRE_ARGS) -{ - - pre_display(mdoc, n); - - if (MDOC_BODY != n->type) - return; - - /* - * The `Dl' (note "el" not "one") and `Bd -literal' and `Bd - * -unfilled' macros set MDOC_LITERAL on entrance to the body. - */ - - switch (n->tok) { - case MDOC_Dl: - mdoc->flags |= MDOC_LITERAL; - break; - case MDOC_Bd: - if (DISP_literal == n->norm->Bd.type) - mdoc->flags |= MDOC_LITERAL; - if (DISP_unfilled == n->norm->Bd.type) - mdoc->flags |= MDOC_LITERAL; - break; - default: - abort(); - /* NOTREACHED */ - } + roff_node_delete(mdoc, mdoc->last); } static void post_dd(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; char *datestr; - if (mdoc->meta.date) + n = mdoc->last; + if (mdoc->meta.date != NULL) { + mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, + n->line, n->pos, "Dd"); free(mdoc->meta.date); + } else if (mdoc->flags & MDOC_PBODY) + mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, + n->line, n->pos, "Dd"); + else if (mdoc->meta.title != NULL) + mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, + n->line, n->pos, "Dd after Dt"); + else if (mdoc->meta.os != NULL) + mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, + n->line, n->pos, "Dd after Os"); - n = mdoc->last; - if (NULL == n->child || '\0' == n->child->string[0]) { + if (n->child == NULL || n->child->string[0] == '\0') { mdoc->meta.date = mdoc->quick ? mandoc_strdup("") : mandoc_normdate(mdoc->parse, NULL, n->line, n->pos); goto out; } datestr = NULL; - mdoc_deroff(&datestr, n); + deroff(&datestr, n); if (mdoc->quick) mdoc->meta.date = datestr; else { @@ -2138,17 +1991,29 @@ post_dd(POST_ARGS) free(datestr); } out: - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } static void post_dt(POST_ARGS) { - struct mdoc_node *nn, *n; + struct roff_node *nn, *n; const char *cp; char *p; n = mdoc->last; + if (mdoc->flags & MDOC_PBODY) { + mandoc_msg(MANDOCERR_DT_LATE, mdoc->parse, + n->line, n->pos, "Dt"); + goto out; + } + + if (mdoc->meta.title != NULL) + mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, + n->line, n->pos, "Dt"); + else if (mdoc->meta.os != NULL) + mandoc_msg(MANDOCERR_PROLOG_ORDER, mdoc->parse, + n->line, n->pos, "Dt after Os"); free(mdoc->meta.title); free(mdoc->meta.msec); @@ -2223,13 +2088,13 @@ post_dt(POST_ARGS) nn->line, nn->pos, "Dt ... %s", nn->string); out: - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } static void post_bx(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; /* * Make `Bx's second argument always start with an uppercase @@ -2237,8 +2102,7 @@ post_bx(POST_ARGS) * uppercase blindly. */ - n = mdoc->last->child; - if (n && NULL != (n = n->next)) + if ((n = mdoc->last->child) != NULL && (n = n->next) != NULL) *n->string = (char)toupper((unsigned char)*n->string); } @@ -2249,9 +2113,15 @@ post_os(POST_ARGS) struct utsname utsname; static char *defbuf; #endif - struct mdoc_node *n; + struct roff_node *n; n = mdoc->last; + if (mdoc->meta.os != NULL) + mandoc_msg(MANDOCERR_PROLOG_REP, mdoc->parse, + n->line, n->pos, "Os"); + else if (mdoc->flags & MDOC_PBODY) + mandoc_msg(MANDOCERR_PROLOG_LATE, mdoc->parse, + n->line, n->pos, "Os"); /* * Set the operating system by way of the `Os' macro. @@ -2264,7 +2134,7 @@ post_os(POST_ARGS) free(mdoc->meta.os); mdoc->meta.os = NULL; - mdoc_deroff(&mdoc->meta.os, n); + deroff(&mdoc->meta.os, n); if (mdoc->meta.os) goto out; @@ -2276,8 +2146,8 @@ post_os(POST_ARGS) #ifdef OSNAME mdoc->meta.os = mandoc_strdup(OSNAME); #else /*!OSNAME */ - if (NULL == defbuf) { - if (-1 == uname(&utsname)) { + if (defbuf == NULL) { + if (uname(&utsname) == -1) { mandoc_msg(MANDOCERR_OS_UNAME, mdoc->parse, n->line, n->pos, "Os"); defbuf = mandoc_strdup("UNKNOWN"); @@ -2289,7 +2159,7 @@ post_os(POST_ARGS) #endif /*!OSNAME*/ out: - mdoc_node_delete(mdoc, n); + roff_node_delete(mdoc, n); } /* @@ -2299,11 +2169,12 @@ out: static void post_ex(POST_ARGS) { - struct mdoc_node *n; + struct roff_node *n; - n = mdoc->last; + post_std(mdoc); - if (n->child) + n = mdoc->last; + if (n->child != NULL) return; if (mdoc->meta.name == NULL) { @@ -2312,112 +2183,112 @@ post_ex(POST_ARGS) return; } - mdoc->next = MDOC_NEXT_CHILD; - mdoc_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name); + mdoc->next = ROFF_NEXT_CHILD; + roff_word_alloc(mdoc, n->line, n->pos, mdoc->meta.name); mdoc->last = n; } -static enum mdoc_sec -a2sec(const char *p) +enum roff_sec +mdoc_a2sec(const char *p) { int i; for (i = 0; i < (int)SEC__MAX; i++) if (secnames[i] && 0 == strcmp(p, secnames[i])) - return((enum mdoc_sec)i); + return (enum roff_sec)i; - return(SEC_CUSTOM); + return SEC_CUSTOM; } static size_t -macro2len(enum mdoct macro) +macro2len(int macro) { switch (macro) { case MDOC_Ad: - return(12); + return 12; case MDOC_Ao: - return(12); + return 12; case MDOC_An: - return(12); + return 12; case MDOC_Aq: - return(12); + return 12; case MDOC_Ar: - return(12); + return 12; case MDOC_Bo: - return(12); + return 12; case MDOC_Bq: - return(12); + return 12; case MDOC_Cd: - return(12); + return 12; case MDOC_Cm: - return(10); + return 10; case MDOC_Do: - return(10); + return 10; case MDOC_Dq: - return(12); + return 12; case MDOC_Dv: - return(12); + return 12; case MDOC_Eo: - return(12); + return 12; case MDOC_Em: - return(10); + return 10; case MDOC_Er: - return(17); + return 17; case MDOC_Ev: - return(15); + return 15; case MDOC_Fa: - return(12); + return 12; case MDOC_Fl: - return(10); + return 10; case MDOC_Fo: - return(16); + return 16; case MDOC_Fn: - return(16); + return 16; case MDOC_Ic: - return(10); + return 10; case MDOC_Li: - return(16); + return 16; case MDOC_Ms: - return(6); + return 6; case MDOC_Nm: - return(10); + return 10; case MDOC_No: - return(12); + return 12; case MDOC_Oo: - return(10); + return 10; case MDOC_Op: - return(14); + return 14; case MDOC_Pa: - return(32); + return 32; case MDOC_Pf: - return(12); + return 12; case MDOC_Po: - return(12); + return 12; case MDOC_Pq: - return(12); + return 12; case MDOC_Ql: - return(16); + return 16; case MDOC_Qo: - return(12); + return 12; case MDOC_So: - return(12); + return 12; case MDOC_Sq: - return(12); + return 12; case MDOC_Sy: - return(6); + return 6; case MDOC_Sx: - return(16); + return 16; case MDOC_Tn: - return(10); + return 10; case MDOC_Va: - return(12); + return 12; case MDOC_Vt: - return(12); + return 12; case MDOC_Xr: - return(10); + return 10; default: break; }; - return(0); + return 0; } diff --git a/usr/src/cmd/mandoc/msec.c b/usr/src/cmd/mandoc/msec.c index d49d2975b6..9d41511696 100644 --- a/usr/src/cmd/mandoc/msec.c +++ b/usr/src/cmd/mandoc/msec.c @@ -1,4 +1,4 @@ -/* $Id: msec.c,v 1.14 2014/12/21 14:14:35 schwarze Exp $ */ +/* $Id: msec.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -32,5 +32,5 @@ mandoc_a2msec(const char *p) #include "msec.in" - return(NULL); + return NULL; } diff --git a/usr/src/cmd/mandoc/out.c b/usr/src/cmd/mandoc/out.c index 53b93fbe00..aff3558372 100644 --- a/usr/src/cmd/mandoc/out.c +++ b/usr/src/cmd/mandoc/out.c @@ -1,4 +1,4 @@ -/* $Id: out.c,v 1.59 2015/01/30 04:11:50 schwarze Exp $ */ +/* $Id: out.c,v 1.62 2015/10/12 00:08:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -51,7 +51,7 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def) dst->unit = def == SCALE_MAX ? SCALE_BU : def; dst->scale = strtod(src, &endptr); if (endptr == src) - return(0); + return 0; switch (*endptr++) { case 'c': @@ -89,12 +89,12 @@ a2roffsu(const char *src, struct roffsu *dst, enum roffscale def) /* FALLTHROUGH */ default: if (SCALE_MAX == def) - return(0); + return 0; dst->unit = def; break; } - return(*endptr == '\0' ? 2 : 1); + return *endptr == '\0' ? 2 : 1; } /* @@ -240,18 +240,14 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col, switch (dp->layout->pos) { case TBL_CELL_HORIZ: - /* FALLTHROUGH */ case TBL_CELL_DHORIZ: sz = (*tbl->len)(1, tbl->arg); if (col->width < sz) col->width = sz; break; case TBL_CELL_LONG: - /* FALLTHROUGH */ case TBL_CELL_CENTRE: - /* FALLTHROUGH */ case TBL_CELL_LEFT: - /* FALLTHROUGH */ case TBL_CELL_RIGHT: tblcalc_literal(tbl, col, dp); break; @@ -262,7 +258,6 @@ tblcalc_data(struct rofftbl *tbl, struct roffcol *col, break; default: abort(); - /* NOTREACHED */ } } diff --git a/usr/src/cmd/mandoc/out.h b/usr/src/cmd/mandoc/out.h index cc218f4fec..2c1cf3fe97 100644 --- a/usr/src/cmd/mandoc/out.h +++ b/usr/src/cmd/mandoc/out.h @@ -1,4 +1,4 @@ -/* $Id: out.h,v 1.26 2014/12/01 08:05:52 schwarze Exp $ */ +/* $Id: out.h,v 1.27 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -60,12 +60,9 @@ struct rofftbl { (p)->scale = (v); } \ while (/* CONSTCOND */ 0) -__BEGIN_DECLS struct tbl_span; int a2roffsu(const char *, struct roffsu *, enum roffscale); void tblcalc(struct rofftbl *tbl, const struct tbl_span *, size_t); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/preconv.c b/usr/src/cmd/mandoc/preconv.c index 87e65ea0c6..1fc137a964 100644 --- a/usr/src/cmd/mandoc/preconv.c +++ b/usr/src/cmd/mandoc/preconv.c @@ -1,4 +1,4 @@ -/* $Id: preconv.c,v 1.14 2015/03/06 09:24:59 kristaps Exp $ */ +/* $Id: preconv.c,v 1.15 2015/10/06 18:32:19 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -92,17 +92,17 @@ preconv_encode(struct buf *ib, size_t *ii, struct buf *ob, size_t *oi, *oi += snprintf(ob->buf + *oi, 11, "\\[u%.4X]", accum); *ii = (char *)cu - ib->buf; *filenc &= ~MPARSE_LATIN1; - return(1); + return 1; latin: if ( ! (*filenc & MPARSE_LATIN1)) - return(0); + return 0; *oi += snprintf(ob->buf + *oi, 11, "\\[u%.4X]", (unsigned char)ib->buf[(*ii)++]); *filenc &= ~MPARSE_UTF8; - return(1); + return 1; } int @@ -123,7 +123,7 @@ preconv_cue(const struct buf *b, size_t offset) if ((sz = (size_t)(eoln - ln)) < 10 || memcmp(ln, ".\\\" -*-", 7) || memcmp(eoln - 3, "-*-", 3)) - return(MPARSE_UTF8 | MPARSE_LATIN1); + return MPARSE_UTF8 | MPARSE_LATIN1; /* Move after the header and adjust for the trailer. */ @@ -162,15 +162,15 @@ preconv_cue(const struct buf *b, size_t offset) sz--; } if (0 == sz) - return(0); + return 0; /* Check us against known encodings. */ if (phsz > 4 && !strncasecmp(ln, "utf-8", 5)) - return(MPARSE_UTF8); + return MPARSE_UTF8; if (phsz > 10 && !strncasecmp(ln, "iso-latin-1", 11)) - return(MPARSE_LATIN1); - return(0); + return MPARSE_LATIN1; + return 0; } - return(MPARSE_UTF8 | MPARSE_LATIN1); + return MPARSE_UTF8 | MPARSE_LATIN1; } diff --git a/usr/src/cmd/mandoc/read.c b/usr/src/cmd/mandoc/read.c index 471d415019..6cbcd2df00 100644 --- a/usr/src/cmd/mandoc/read.c +++ b/usr/src/cmd/mandoc/read.c @@ -1,16 +1,16 @@ -/* $Id: read.c,v 1.131 2015/03/11 13:05:20 schwarze Exp $ */ +/* $Id: read.c,v 1.149 2016/07/10 13:34:30 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2010-2016 Ingo Schwarze <schwarze@openbsd.org> * Copyright (c) 2010, 2012 Joerg Sonnenberger <joerg@netbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -23,10 +23,12 @@ #include <sys/mman.h> #include <sys/stat.h> #endif -#include <sys/wait.h> #include <assert.h> #include <ctype.h> +#if HAVE_ERR +#include <err.h> +#endif #include <errno.h> #include <fcntl.h> #include <stdarg.h> @@ -35,22 +37,21 @@ #include <stdlib.h> #include <string.h> #include <unistd.h> +#include <zlib.h> -#include "mandoc.h" #include "mandoc_aux.h" -#include "libmandoc.h" +#include "mandoc.h" +#include "roff.h" #include "mdoc.h" #include "man.h" +#include "libmandoc.h" +#include "roff_int.h" #define REPARSE_LIMIT 1000 struct mparse { - struct man *pman; /* persistent man parser */ - struct mdoc *pmdoc; /* persistent mdoc parser */ - struct man *man; /* man parser */ - struct mdoc *mdoc; /* mdoc parser */ + struct roff_man *man; /* man parser */ struct roff *roff; /* roff parser (!NULL) */ - const struct mchars *mchars; /* character table */ char *sodest; /* filename pointed to by .so */ const char *file; /* filename of current input file */ struct buf *primary; /* buffer currently being parsed */ @@ -60,10 +61,10 @@ struct mparse { enum mandoclevel file_status; /* status of current parse */ enum mandoclevel wlevel; /* ignore messages below this */ int options; /* parser options */ + int gzip; /* current input file is gzipped */ int filenc; /* encoding of the current file */ int reparse_count; /* finite interp. stack */ int line; /* line number in the file */ - pid_t child; /* the gunzip(1) process */ }; static void choose_parser(struct mparse *); @@ -130,7 +131,6 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { "blocks badly nested", "nested displays are not portable", "moving content out of list", - ".Vt block has child macro", "fill mode already enabled, skipping", "fill mode already disabled, skipping", "line scope broken", @@ -217,6 +217,7 @@ static const char * const mandocerrs[MANDOCERR_MAX] = { /* related to request and macro arguments */ "escaped character not allowed in a name", "NOT IMPLEMENTED: Bd -file", + "skipping display without arguments", "missing list type, using -item", "missing manual name, using \"\"", "uname(3) system call failed, using UNKNOWN", @@ -290,24 +291,22 @@ choose_parser(struct mparse *curp) } } - if (format == MPARSE_MDOC) { - if (NULL == curp->pmdoc) - curp->pmdoc = mdoc_alloc( - curp->roff, curp, curp->defos, - MPARSE_QUICK & curp->options ? 1 : 0); - assert(curp->pmdoc); - curp->mdoc = curp->pmdoc; - return; + if (curp->man == NULL) { + curp->man = roff_man_alloc(curp->roff, curp, curp->defos, + curp->options & MPARSE_QUICK ? 1 : 0); + curp->man->macroset = MACROSET_MAN; + curp->man->first->tok = TOKEN_NONE; } - /* Fall back to man(7) as a last resort. */ - - if (NULL == curp->pman) - curp->pman = man_alloc( - curp->roff, curp, curp->defos, - MPARSE_QUICK & curp->options ? 1 : 0); - assert(curp->pman); - curp->man = curp->pman; + if (format == MPARSE_MDOC) { + mdoc_hash_init(); + curp->man->macroset = MACROSET_MDOC; + curp->man->first->tok = TOKEN_NONE; + } else { + man_hash_init(); + curp->man->macroset = MACROSET_MAN; + curp->man->first->tok = TOKEN_NONE; + } } /* @@ -329,7 +328,6 @@ mparse_buf_r(struct mparse *curp, struct buf blk, size_t i, int start) int of; int lnn; /* line number in the real file */ int fd; - pid_t save_child; unsigned char c; memset(&ln, 0, sizeof(ln)); @@ -541,10 +539,9 @@ rerun: if (curp->secondary) curp->secondary->sz -= pos + 1; save_file = curp->file; - save_child = curp->child; - if (mparse_open(curp, &fd, ln.buf + of) == - MANDOCLEVEL_OK) { + if ((fd = mparse_open(curp, ln.buf + of)) != -1) { mparse_readfd(curp, fd, ln.buf + of); + close(fd); curp->file = save_file; } else { curp->file = save_file; @@ -559,7 +556,6 @@ rerun: of = 0; mparse_buf_r(curp, ln, of, 0); } - curp->child = save_child; pos = 0; continue; default: @@ -573,7 +569,8 @@ rerun: * parsers with each one. */ - if ( ! (curp->man || curp->mdoc)) + if (curp->man == NULL || + curp->man->macroset == MACROSET_NONE) choose_parser(curp); /* @@ -585,19 +582,13 @@ rerun: * Do the same for ROFF_EQN. */ - if (rr == ROFF_TBL) { + if (rr == ROFF_TBL) while ((span = roff_span(curp->roff)) != NULL) - if (curp->man == NULL) - mdoc_addspan(curp->mdoc, span); - else - man_addspan(curp->man, span); - } else if (rr == ROFF_EQN) { - if (curp->man == NULL) - mdoc_addeqn(curp->mdoc, roff_eqn(curp->roff)); - else - man_addeqn(curp->man, roff_eqn(curp->roff)); - } else if ((curp->man == NULL ? - mdoc_parseln(curp->mdoc, curp->line, ln.buf, of) : + roff_addtbl(curp->man, span); + else if (rr == ROFF_EQN) + roff_addeqn(curp->man, roff_eqn(curp->roff)); + else if ((curp->man->macroset == MACROSET_MDOC ? + mdoc_parseln(curp->man, curp->line, ln.buf, of) : man_parseln(curp->man, curp->line, ln.buf, of)) == 2) break; @@ -618,15 +609,15 @@ static int read_whole_file(struct mparse *curp, const char *file, int fd, struct buf *fb, int *with_mmap) { + gzFile gz; size_t off; ssize_t ssz; #if HAVE_MMAP struct stat st; - if (-1 == fstat(fd, &st)) { - perror(file); - exit((int)MANDOCLEVEL_SYSERR); - } + + if (fstat(fd, &st) == -1) + err((int)MANDOCLEVEL_SYSERR, "%s", file); /* * If we're a regular file, try just reading in the whole entry @@ -635,19 +626,25 @@ read_whole_file(struct mparse *curp, const char *file, int fd, * concerned that this is going to tank any machines. */ - if (S_ISREG(st.st_mode)) { + if (curp->gzip == 0 && S_ISREG(st.st_mode)) { if (st.st_size > 0x7fffffff) { mandoc_msg(MANDOCERR_TOOLARGE, curp, 0, 0, NULL); - return(0); + return 0; } *with_mmap = 1; fb->sz = (size_t)st.st_size; fb->buf = mmap(NULL, fb->sz, PROT_READ, MAP_SHARED, fd, 0); if (fb->buf != MAP_FAILED) - return(1); + return 1; } #endif + if (curp->gzip) { + if ((gz = gzdopen(fd, "rb")) == NULL) + err((int)MANDOCLEVEL_SYSERR, "%s", file); + } else + gz = NULL; + /* * If this isn't a regular file (like, say, stdin), then we must * go the old way and just read things in bit by bit. @@ -666,43 +663,35 @@ read_whole_file(struct mparse *curp, const char *file, int fd, } resize_buf(fb, 65536); } - ssz = read(fd, fb->buf + (int)off, fb->sz - off); + ssz = curp->gzip ? + gzread(gz, fb->buf + (int)off, fb->sz - off) : + read(fd, fb->buf + (int)off, fb->sz - off); if (ssz == 0) { fb->sz = off; - return(1); - } - if (ssz == -1) { - perror(file); - exit((int)MANDOCLEVEL_SYSERR); + return 1; } + if (ssz == -1) + err((int)MANDOCLEVEL_SYSERR, "%s", file); off += (size_t)ssz; } free(fb->buf); fb->buf = NULL; - return(0); + return 0; } static void mparse_end(struct mparse *curp) { - if (curp->mdoc == NULL && - curp->man == NULL && - curp->sodest == NULL) { - if (curp->options & MPARSE_MDOC) - curp->mdoc = curp->pmdoc; - else { - if (curp->pman == NULL) - curp->pman = man_alloc( - curp->roff, curp, curp->defos, - curp->options & MPARSE_QUICK ? 1 : 0); - curp->man = curp->pman; - } - } - if (curp->mdoc) - mdoc_endparse(curp->mdoc); - if (curp->man) + if (curp->man == NULL && curp->sodest == NULL) + curp->man = roff_man_alloc(curp->roff, curp, curp->defos, + curp->options & MPARSE_QUICK ? 1 : 0); + if (curp->man->macroset == MACROSET_NONE) + curp->man->macroset = MACROSET_MAN; + if (curp->man->macroset == MACROSET_MDOC) + mdoc_endparse(curp->man); + else man_endparse(curp->man); roff_endparse(curp->roff); } @@ -757,7 +746,7 @@ mparse_readmem(struct mparse *curp, void *buf, size_t len, blk.sz = len; mparse_parse_buffer(curp, blk, file); - return(curp->file_status); + return curp->file_status; } /* @@ -784,107 +773,48 @@ mparse_readfd(struct mparse *curp, int fd, const char *file) #endif free(blk.buf); } - - if (fd != STDIN_FILENO && close(fd) == -1) - perror(file); - - mparse_wait(curp); - return(curp->file_status); + return curp->file_status; } -enum mandoclevel -mparse_open(struct mparse *curp, int *fd, const char *file) +int +mparse_open(struct mparse *curp, const char *file) { - int pfd[2]; - int save_errno; char *cp; + int fd; curp->file = file; + cp = strrchr(file, '.'); + curp->gzip = (cp != NULL && ! strcmp(cp + 1, "gz")); - /* Unless zipped, try to just open the file. */ + /* First try to use the filename as it is. */ - if ((cp = strrchr(file, '.')) == NULL || - strcmp(cp + 1, "gz")) { - curp->child = 0; - if ((*fd = open(file, O_RDONLY)) != -1) - return(MANDOCLEVEL_OK); + if ((fd = open(file, O_RDONLY)) != -1) + return fd; - /* Open failed; try to append ".gz". */ + /* + * If that doesn't work and the filename doesn't + * already end in .gz, try appending .gz. + */ + if ( ! curp->gzip) { mandoc_asprintf(&cp, "%s.gz", file); - file = cp; - } else - cp = NULL; - - /* Before forking, make sure the file can be read. */ - - save_errno = errno; - if (access(file, R_OK) == -1) { - if (cp != NULL) - errno = save_errno; + fd = open(cp, O_RDONLY); free(cp); - *fd = -1; - curp->child = 0; - mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno)); - return(MANDOCLEVEL_ERROR); - } - - /* Run gunzip(1). */ - - if (pipe(pfd) == -1) { - perror("pipe"); - exit((int)MANDOCLEVEL_SYSERR); - } - - switch (curp->child = fork()) { - case -1: - perror("fork"); - exit((int)MANDOCLEVEL_SYSERR); - case 0: - close(pfd[0]); - if (dup2(pfd[1], STDOUT_FILENO) == -1) { - perror("dup"); - exit((int)MANDOCLEVEL_SYSERR); + if (fd != -1) { + curp->gzip = 1; + return fd; } - execlp("gunzip", "gunzip", "-c", file, NULL); - perror("exec"); - exit((int)MANDOCLEVEL_SYSERR); - default: - close(pfd[1]); - *fd = pfd[0]; - return(MANDOCLEVEL_OK); } -} - -enum mandoclevel -mparse_wait(struct mparse *curp) -{ - int status; - if (curp->child == 0) - return(MANDOCLEVEL_OK); + /* Neither worked, give up. */ - if (waitpid(curp->child, &status, 0) == -1) { - perror("wait"); - exit((int)MANDOCLEVEL_SYSERR); - } - curp->child = 0; - if (WIFSIGNALED(status)) { - mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, - "gunzip died from signal %d", WTERMSIG(status)); - return(MANDOCLEVEL_ERROR); - } - if (WEXITSTATUS(status)) { - mandoc_vmsg(MANDOCERR_FILE, curp, 0, 0, - "gunzip failed with code %d", WEXITSTATUS(status)); - return(MANDOCLEVEL_ERROR); - } - return(MANDOCLEVEL_OK); + mandoc_msg(MANDOCERR_FILE, curp, 0, 0, strerror(errno)); + return -1; } struct mparse * mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg, - const struct mchars *mchars, const char *defos) + const char *defos) { struct mparse *curp; @@ -895,18 +825,18 @@ mparse_alloc(int options, enum mandoclevel wlevel, mandocmsg mmsg, curp->mmsg = mmsg; curp->defos = defos; - curp->mchars = mchars; - curp->roff = roff_alloc(curp, curp->mchars, options); - if (curp->options & MPARSE_MDOC) - curp->pmdoc = mdoc_alloc( - curp->roff, curp, curp->defos, - curp->options & MPARSE_QUICK ? 1 : 0); - if (curp->options & MPARSE_MAN) - curp->pman = man_alloc( - curp->roff, curp, curp->defos, - curp->options & MPARSE_QUICK ? 1 : 0); - - return(curp); + curp->roff = roff_alloc(curp, options); + curp->man = roff_man_alloc( curp->roff, curp, curp->defos, + curp->options & MPARSE_QUICK ? 1 : 0); + if (curp->options & MPARSE_MDOC) { + mdoc_hash_init(); + curp->man->macroset = MACROSET_MDOC; + } else if (curp->options & MPARSE_MAN) { + man_hash_init(); + curp->man->macroset = MACROSET_MAN; + } + curp->man->first->tok = TOKEN_NONE; + return curp; } void @@ -915,16 +845,12 @@ mparse_reset(struct mparse *curp) roff_reset(curp->roff); - if (curp->mdoc) - mdoc_reset(curp->mdoc); - if (curp->man) - man_reset(curp->man); + if (curp->man != NULL) + roff_man_reset(curp->man); if (curp->secondary) curp->secondary->sz = 0; curp->file_status = MANDOCLEVEL_OK; - curp->mdoc = NULL; - curp->man = NULL; free(curp->sodest); curp->sodest = NULL; @@ -934,10 +860,7 @@ void mparse_free(struct mparse *curp) { - if (curp->pmdoc) - mdoc_free(curp->pmdoc); - if (curp->pman) - man_free(curp->pman); + roff_man_free(curp->man); if (curp->roff) roff_free(curp->roff); if (curp->secondary) @@ -949,17 +872,14 @@ mparse_free(struct mparse *curp) } void -mparse_result(struct mparse *curp, - struct mdoc **mdoc, struct man **man, char **sodest) +mparse_result(struct mparse *curp, struct roff_man **man, + char **sodest) { if (sodest && NULL != (*sodest = curp->sodest)) { - *mdoc = NULL; *man = NULL; return; } - if (mdoc) - *mdoc = curp->mdoc; if (man) *man = curp->man; } @@ -1002,13 +922,13 @@ const char * mparse_strerror(enum mandocerr er) { - return(mandocerrs[er]); + return mandocerrs[er]; } const char * mparse_strlevel(enum mandoclevel lvl) { - return(mandoclevels[lvl]); + return mandoclevels[lvl]; } void @@ -1024,5 +944,5 @@ mparse_getkeep(const struct mparse *p) { assert(p->secondary); - return(p->secondary->sz ? p->secondary->buf : NULL); + return p->secondary->sz ? p->secondary->buf : NULL; } diff --git a/usr/src/cmd/mandoc/roff.c b/usr/src/cmd/mandoc/roff.c index 3c920137ea..13b9439e4d 100644 --- a/usr/src/cmd/mandoc/roff.c +++ b/usr/src/cmd/mandoc/roff.c @@ -1,6 +1,6 @@ -/* $Id: roff.c,v 1.263 2015/02/21 14:46:58 schwarze Exp $ */ +/* $Id: roff.c,v 1.284 2016/01/08 17:48:10 schwarze Exp $ */ /* - * Copyright (c) 2010, 2011, 2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2008-2012, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any @@ -28,15 +28,16 @@ #include "mandoc.h" #include "mandoc_aux.h" +#include "roff.h" #include "libmandoc.h" +#include "roff_int.h" #include "libroff.h" -/* Maximum number of nested if-else conditionals. */ -#define RSTACK_MAX 128 - /* Maximum number of string expansions per line, to break infinite loops. */ #define EXPAND_LIMIT 1000 +/* --- data types --------------------------------------------------------- */ + enum rofft { ROFF_ab, ROFF_ad, @@ -312,7 +313,6 @@ struct roffreg { struct roff { struct mparse *parse; /* parse point */ - const struct mchars *mchars; /* character table */ struct roffnode *last; /* leaf of stack */ int *rstack; /* stack of inverted `ie' values */ struct roffreg *regtab; /* number registers */ @@ -331,6 +331,7 @@ struct roff { int rstacksz; /* current size limit of rstack */ int rstackpos; /* position in rstack */ int format; /* current file in mdoc or man format */ + int argc; /* number of args of the last macro */ char control; /* control character */ }; @@ -373,6 +374,8 @@ struct predef { #define PREDEF(__name, __str) \ { (__name), (__str) }, +/* --- function prototypes ------------------------------------------------ */ + static enum rofft roffhash_find(const char *, size_t); static void roffhash_init(void); static void roffnode_cleanscope(struct roff *); @@ -391,8 +394,7 @@ static enum rofferr roff_cond_text(ROFF_ARGS); static enum rofferr roff_cond_sub(ROFF_ARGS); static enum rofferr roff_ds(ROFF_ARGS); static enum rofferr roff_eqndelim(struct roff *, struct buf *, int); -static int roff_evalcond(struct roff *r, int, - const char *, int *); +static int roff_evalcond(struct roff *r, int, char *, int *); static int roff_evalnum(struct roff *, int, const char *, int *, int *, int); static int roff_evalpar(struct roff *, int, @@ -406,12 +408,17 @@ static int roff_getnum(const char *, int *, int *, int); static int roff_getop(const char *, int *, char *); static int roff_getregn(const struct roff *, const char *, size_t); -static int roff_getregro(const char *name); +static int roff_getregro(const struct roff *, + const char *name); static const char *roff_getstrn(const struct roff *, const char *, size_t); +static int roff_hasregn(const struct roff *, + const char *, size_t); static enum rofferr roff_insec(ROFF_ARGS); static enum rofferr roff_it(ROFF_ARGS); static enum rofferr roff_line_ignore(ROFF_ARGS); +static void roff_man_alloc1(struct roff_man *); +static void roff_man_free1(struct roff_man *); static enum rofferr roff_nr(ROFF_ARGS); static enum rofft roff_parse(struct roff *, char *, int *, int, int); @@ -435,6 +442,8 @@ static enum rofferr roff_T_(ROFF_ARGS); static enum rofferr roff_unsupp(ROFF_ARGS); static enum rofferr roff_userdef(ROFF_ARGS); +/* --- constant data ------------------------------------------------------ */ + /* See roffhash_find() */ #define ASCII_HI 126 @@ -731,6 +740,8 @@ static int roffit_lines; /* number of lines to delay */ static char *roffit_macro; /* nil-terminated macro line */ +/* --- request table ------------------------------------------------------ */ + static void roffhash_init(void) { @@ -770,19 +781,21 @@ roffhash_find(const char *p, size_t s) */ if (p[0] < ASCII_LO || p[0] > ASCII_HI) - return(ROFF_MAX); + return ROFF_MAX; buc = ROFF_HASH(p); if (NULL == (n = hash[buc])) - return(ROFF_MAX); + return ROFF_MAX; for ( ; n; n = n->next) if (0 == strncmp(n->name, p, s) && '\0' == n->name[(int)s]) - return((enum rofft)(n - roffs)); + return (enum rofft)(n - roffs); - return(ROFF_MAX); + return ROFF_MAX; } +/* --- stack of request blocks -------------------------------------------- */ + /* * Pop the current node off of the stack of roff instructions currently * pending. @@ -823,6 +836,8 @@ roffnode_push(struct roff *r, enum rofft tok, const char *name, r->last = p; } +/* --- roff parser state data management ---------------------------------- */ + static void roff_free1(struct roff *r) { @@ -882,22 +897,370 @@ roff_free(struct roff *r) } struct roff * -roff_alloc(struct mparse *parse, const struct mchars *mchars, int options) +roff_alloc(struct mparse *parse, int options) { struct roff *r; r = mandoc_calloc(1, sizeof(struct roff)); r->parse = parse; - r->mchars = mchars; r->options = options; r->format = options & (MPARSE_MDOC | MPARSE_MAN); r->rstackpos = -1; roffhash_init(); - return(r); + return r; +} + +/* --- syntax tree state data management ---------------------------------- */ + +static void +roff_man_free1(struct roff_man *man) +{ + + if (man->first != NULL) + roff_node_delete(man, man->first); + free(man->meta.msec); + free(man->meta.vol); + free(man->meta.os); + free(man->meta.arch); + free(man->meta.title); + free(man->meta.name); + free(man->meta.date); +} + +static void +roff_man_alloc1(struct roff_man *man) +{ + + memset(&man->meta, 0, sizeof(man->meta)); + man->first = mandoc_calloc(1, sizeof(*man->first)); + man->first->type = ROFFT_ROOT; + man->last = man->first; + man->last_es = NULL; + man->flags = 0; + man->macroset = MACROSET_NONE; + man->lastsec = man->lastnamed = SEC_NONE; + man->next = ROFF_NEXT_CHILD; +} + +void +roff_man_reset(struct roff_man *man) +{ + + roff_man_free1(man); + roff_man_alloc1(man); +} + +void +roff_man_free(struct roff_man *man) +{ + + roff_man_free1(man); + free(man); +} + +struct roff_man * +roff_man_alloc(struct roff *roff, struct mparse *parse, + const char *defos, int quick) +{ + struct roff_man *man; + + man = mandoc_calloc(1, sizeof(*man)); + man->parse = parse; + man->roff = roff; + man->defos = defos; + man->quick = quick; + roff_man_alloc1(man); + return man; +} + +/* --- syntax tree handling ----------------------------------------------- */ + +struct roff_node * +roff_node_alloc(struct roff_man *man, int line, int pos, + enum roff_type type, int tok) +{ + struct roff_node *n; + + n = mandoc_calloc(1, sizeof(*n)); + n->line = line; + n->pos = pos; + n->tok = tok; + n->type = type; + n->sec = man->lastsec; + + if (man->flags & MDOC_SYNOPSIS) + n->flags |= MDOC_SYNPRETTY; + else + n->flags &= ~MDOC_SYNPRETTY; + if (man->flags & MDOC_NEWLINE) + n->flags |= MDOC_LINE; + man->flags &= ~MDOC_NEWLINE; + + return n; +} + +void +roff_node_append(struct roff_man *man, struct roff_node *n) +{ + + switch (man->next) { + case ROFF_NEXT_SIBLING: + if (man->last->next != NULL) { + n->next = man->last->next; + man->last->next->prev = n; + } else + man->last->parent->last = n; + man->last->next = n; + n->prev = man->last; + n->parent = man->last->parent; + break; + case ROFF_NEXT_CHILD: + man->last->child = n; + n->parent = man->last; + n->parent->last = n; + break; + default: + abort(); + } + man->last = n; + + switch (n->type) { + case ROFFT_HEAD: + n->parent->head = n; + break; + case ROFFT_BODY: + if (n->end != ENDBODY_NOT) + return; + n->parent->body = n; + break; + case ROFFT_TAIL: + n->parent->tail = n; + break; + default: + return; + } + + /* + * Copy over the normalised-data pointer of our parent. Not + * everybody has one, but copying a null pointer is fine. + */ + + n->norm = n->parent->norm; + assert(n->parent->type == ROFFT_BLOCK); +} + +void +roff_word_alloc(struct roff_man *man, int line, int pos, const char *word) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_TEXT, TOKEN_NONE); + n->string = roff_strdup(man->roff, word); + roff_node_append(man, n); + if (man->macroset == MACROSET_MDOC) + n->flags |= MDOC_VALID | MDOC_ENDED; + else + n->flags |= MAN_VALID; + man->next = ROFF_NEXT_SIBLING; +} + +void +roff_word_append(struct roff_man *man, const char *word) +{ + struct roff_node *n; + char *addstr, *newstr; + + n = man->last; + addstr = roff_strdup(man->roff, word); + mandoc_asprintf(&newstr, "%s %s", n->string, addstr); + free(addstr); + free(n->string); + n->string = newstr; + man->next = ROFF_NEXT_SIBLING; +} + +void +roff_elem_alloc(struct roff_man *man, int line, int pos, int tok) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_ELEM, tok); + roff_node_append(man, n); + man->next = ROFF_NEXT_CHILD; +} + +struct roff_node * +roff_block_alloc(struct roff_man *man, int line, int pos, int tok) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_BLOCK, tok); + roff_node_append(man, n); + man->next = ROFF_NEXT_CHILD; + return n; +} + +struct roff_node * +roff_head_alloc(struct roff_man *man, int line, int pos, int tok) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_HEAD, tok); + roff_node_append(man, n); + man->next = ROFF_NEXT_CHILD; + return n; +} + +struct roff_node * +roff_body_alloc(struct roff_man *man, int line, int pos, int tok) +{ + struct roff_node *n; + + n = roff_node_alloc(man, line, pos, ROFFT_BODY, tok); + roff_node_append(man, n); + man->next = ROFF_NEXT_CHILD; + return n; +} + +void +roff_addeqn(struct roff_man *man, const struct eqn *eqn) +{ + struct roff_node *n; + + n = roff_node_alloc(man, eqn->ln, eqn->pos, ROFFT_EQN, TOKEN_NONE); + n->eqn = eqn; + if (eqn->ln > man->last->line) + n->flags |= MDOC_LINE; + roff_node_append(man, n); + man->next = ROFF_NEXT_SIBLING; +} + +void +roff_addtbl(struct roff_man *man, const struct tbl_span *tbl) +{ + struct roff_node *n; + + if (man->macroset == MACROSET_MAN) + man_breakscope(man, TOKEN_NONE); + n = roff_node_alloc(man, tbl->line, 0, ROFFT_TBL, TOKEN_NONE); + n->span = tbl; + roff_node_append(man, n); + if (man->macroset == MACROSET_MDOC) + n->flags |= MDOC_VALID | MDOC_ENDED; + else + n->flags |= MAN_VALID; + man->next = ROFF_NEXT_SIBLING; +} + +void +roff_node_unlink(struct roff_man *man, struct roff_node *n) +{ + + /* Adjust siblings. */ + + if (n->prev) + n->prev->next = n->next; + if (n->next) + n->next->prev = n->prev; + + /* Adjust parent. */ + + if (n->parent != NULL) { + if (n->parent->child == n) + n->parent->child = n->next; + if (n->parent->last == n) + n->parent->last = n->prev; + } + + /* Adjust parse point. */ + + if (man == NULL) + return; + if (man->last == n) { + if (n->prev == NULL) { + man->last = n->parent; + man->next = ROFF_NEXT_CHILD; + } else { + man->last = n->prev; + man->next = ROFF_NEXT_SIBLING; + } + } + if (man->first == n) + man->first = NULL; +} + +void +roff_node_free(struct roff_node *n) +{ + + if (n->args != NULL) + mdoc_argv_free(n->args); + if (n->type == ROFFT_BLOCK || n->type == ROFFT_ELEM) + free(n->norm); + free(n->string); + free(n); +} + +void +roff_node_delete(struct roff_man *man, struct roff_node *n) +{ + + while (n->child != NULL) + roff_node_delete(man, n->child); + roff_node_unlink(man, n); + roff_node_free(n); } +void +deroff(char **dest, const struct roff_node *n) +{ + char *cp; + size_t sz; + + if (n->type != ROFFT_TEXT) { + for (n = n->child; n != NULL; n = n->next) + deroff(dest, n); + return; + } + + /* Skip leading whitespace and escape sequences. */ + + cp = n->string; + while (*cp != '\0') { + if ('\\' == *cp) { + cp++; + mandoc_escape((const char **)&cp, NULL, NULL); + } else if (isspace((unsigned char)*cp)) + cp++; + else + break; + } + + /* Skip trailing whitespace. */ + + for (sz = strlen(cp); sz; sz--) + if ( ! isspace((unsigned char)cp[sz-1])) + break; + + /* Skip empty strings. */ + + if (sz == 0) + return; + + if (*dest == NULL) { + *dest = mandoc_strndup(cp, sz); + return; + } + + mandoc_asprintf(&cp, "%s %*s", *dest, (int)sz, cp); + free(*dest); + *dest = cp; +} + +/* --- main functions of the roff parser ---------------------------------- */ + /* * In the current line, expand escape sequences that tend to get * used in numerical expressions and conditional requests. @@ -952,7 +1315,6 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) res = NULL; break; case 'B': - /* FALLTHROUGH */ case 'w': term = cp[1]; /* FALLTHROUGH */ @@ -963,7 +1325,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) esc = mandoc_escape(&cp, &stnam, &inaml); if (esc == ESCAPE_ERROR || (esc == ESCAPE_SPECIAL && - mchars_spec2cp(r->mchars, stnam, inaml) < 0)) + mchars_spec2cp(stnam, inaml) < 0)) mandoc_vmsg(MANDOCERR_ESC_BAD, r->parse, ln, (int)(stesc - buf->buf), "%.*s", (int)(cp - stesc), stesc); @@ -973,7 +1335,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) if (EXPAND_LIMIT < ++expand_count) { mandoc_msg(MANDOCERR_ROFFLOOP, r->parse, ln, (int)(stesc - buf->buf), NULL); - return(ROFF_IGN); + return ROFF_IGN; } /* @@ -1027,11 +1389,8 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) } switch (mandoc_escape(&cp, NULL, NULL)) { case ESCAPE_SPECIAL: - /* FALLTHROUGH */ case ESCAPE_UNICODE: - /* FALLTHROUGH */ case ESCAPE_NUMBERED: - /* FALLTHROUGH */ case ESCAPE_OVERSTRIKE: naml++; break; @@ -1080,7 +1439,7 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) } else if (buf->sz + strlen(res) > SHRT_MAX) { mandoc_msg(MANDOCERR_ROFFLOOP, r->parse, ln, (int)(stesc - buf->buf), NULL); - return(ROFF_IGN); + return ROFF_IGN; } /* Replace the escape sequence by the string. */ @@ -1096,13 +1455,11 @@ roff_res(struct roff *r, struct buf *buf, int ln, int pos) free(buf->buf); buf->buf = nbuf; } - return(ROFF_CONT); + return ROFF_CONT; } /* - * Process text streams: - * Convert all breakable hyphens into ASCII_HYPH. - * Decrement and spring input line trap. + * Process text streams. */ static enum rofferr roff_parsetext(struct buf *buf, int pos, int *offs) @@ -1113,6 +1470,22 @@ roff_parsetext(struct buf *buf, int pos, int *offs) int isz; enum mandoc_esc esc; + /* Spring the input line trap. */ + + if (roffit_lines == 1) { + isz = mandoc_asprintf(&p, "%s\n.%s", buf->buf, roffit_macro); + free(buf->buf); + buf->buf = p; + buf->sz = isz + 1; + *offs = 0; + free(roffit_macro); + roffit_lines = 0; + return ROFF_REPARSE; + } else if (roffit_lines > 1) + --roffit_lines; + + /* Convert all breakable hyphens into ASCII_HYPH. */ + start = p = buf->buf + pos; while (*p != '\0') { @@ -1128,6 +1501,8 @@ roff_parsetext(struct buf *buf, int pos, int *offs) esc = mandoc_escape((const char **)&p, NULL, NULL); if (esc == ESCAPE_ERROR) break; + while (*p == '-') + p++; continue; } else if (p == start) { p++; @@ -1139,20 +1514,7 @@ roff_parsetext(struct buf *buf, int pos, int *offs) *p = ASCII_HYPH; p++; } - - /* Spring the input line trap. */ - if (roffit_lines == 1) { - isz = mandoc_asprintf(&p, "%s\n.%s", buf->buf, roffit_macro); - free(buf->buf); - buf->buf = p; - buf->sz = isz + 1; - *offs = 0; - free(roffit_macro); - roffit_lines = 0; - return(ROFF_REPARSE); - } else if (roffit_lines > 1) - --roffit_lines; - return(ROFF_CONT); + return ROFF_CONT; } enum rofferr @@ -1174,7 +1536,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) (r->eqn == NULL || r->eqn_inline)) { e = roff_eqndelim(r, buf, pos); if (e == ROFF_REPARSE) - return(e); + return e; assert(e == ROFF_CONT); } @@ -1182,7 +1544,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) e = roff_res(r, buf, ln, pos); if (e == ROFF_IGN) - return(e); + return e; assert(e == ROFF_CONT); ctl = roff_getcontrol(r, buf->buf, &pos); @@ -1201,23 +1563,23 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) e = (*roffs[t].text)(r, t, buf, ln, pos, pos, offs); assert(e == ROFF_IGN || e == ROFF_CONT); if (e != ROFF_CONT) - return(e); + return e; } if (r->eqn != NULL) - return(eqn_read(&r->eqn, ln, buf->buf, ppos, offs)); + return eqn_read(&r->eqn, ln, buf->buf, ppos, offs); if (r->tbl != NULL && ( ! ctl || buf->buf[pos] == '\0')) - return(tbl_read(r->tbl, ln, buf->buf, ppos)); + return tbl_read(r->tbl, ln, buf->buf, ppos); if ( ! ctl) - return(roff_parsetext(buf, pos, offs)); + return roff_parsetext(buf, pos, offs); /* Skip empty request lines. */ if (buf->buf[pos] == '"') { mandoc_msg(MANDOCERR_COMMENT_BAD, r->parse, ln, pos, NULL); - return(ROFF_IGN); + return ROFF_IGN; } else if (buf->buf[pos] == '\0') - return(ROFF_IGN); + return ROFF_IGN; /* * If a scope is open, go to the child handler for that macro, @@ -1228,7 +1590,7 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) if (r->last) { t = r->last->tok; assert(roffs[t].sub); - return((*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs)); + return (*roffs[t].sub)(r, t, buf, ln, ppos, pos, offs); } /* No scope is open. This is a new request or macro. */ @@ -1242,12 +1604,12 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) mandoc_msg(MANDOCERR_TBLMACRO, r->parse, ln, pos, buf->buf + spos); if (t == ROFF_TS) - return(ROFF_IGN); + return ROFF_IGN; while (buf->buf[pos] != '\0' && buf->buf[pos] != ' ') pos++; while (buf->buf[pos] != '\0' && buf->buf[pos] == ' ') pos++; - return(tbl_read(r->tbl, ln, buf->buf, pos)); + return tbl_read(r->tbl, ln, buf->buf, pos); } /* @@ -1256,12 +1618,12 @@ roff_parseln(struct roff *r, int ln, struct buf *buf, int *offs) */ if (t == ROFF_MAX) - return(ROFF_CONT); + return ROFF_CONT; /* Execute a roff request or a user defined macro. */ assert(roffs[t].proc); - return((*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs)); + return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs); } void @@ -1301,7 +1663,7 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos) cp = buf + *pos; if ('\0' == *cp || '"' == *cp || '\t' == *cp || ' ' == *cp) - return(ROFF_MAX); + return ROFF_MAX; mac = cp; maclen = roff_getname(r, &cp, ln, ppos); @@ -1312,9 +1674,11 @@ roff_parse(struct roff *r, char *buf, int *pos, int ln, int ppos) if (ROFF_MAX != t) *pos = cp - buf; - return(t); + return t; } +/* --- handling of request blocks ----------------------------------------- */ + static enum rofferr roff_cblock(ROFF_ARGS) { @@ -1327,26 +1691,22 @@ roff_cblock(ROFF_ARGS) if (r->last == NULL) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, ".."); - return(ROFF_IGN); + return ROFF_IGN; } switch (r->last->tok) { case ROFF_am: /* ROFF_am1 is remapped to ROFF_am in roff_block(). */ - /* FALLTHROUGH */ case ROFF_ami: - /* FALLTHROUGH */ case ROFF_de: /* ROFF_de1 is remapped to ROFF_de in roff_block(). */ - /* FALLTHROUGH */ case ROFF_dei: - /* FALLTHROUGH */ case ROFF_ig: break; default: mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, ".."); - return(ROFF_IGN); + return ROFF_IGN; } if (buf->buf[pos] != '\0') @@ -1355,7 +1715,7 @@ roff_cblock(ROFF_ARGS) roffnode_pop(r); roffnode_cleanscope(r); - return(ROFF_IGN); + return ROFF_IGN; } @@ -1382,9 +1742,7 @@ roff_ccond(struct roff *r, int ln, int ppos) switch (r->last->tok) { case ROFF_el: - /* FALLTHROUGH */ case ROFF_ie: - /* FALLTHROUGH */ case ROFF_if: break; default: @@ -1450,7 +1808,7 @@ roff_block(ROFF_ARGS) if (namesz == 0 && tok != ROFF_ig) { mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse, ln, ppos, roffs[tok].name); - return(ROFF_IGN); + return ROFF_IGN; } roffnode_push(r, tok, name, ln, ppos); @@ -1465,7 +1823,7 @@ roff_block(ROFF_ARGS) roff_setstrn(&r->strtab, name, namesz, "", 0, 0); if (*cp == '\0') - return(ROFF_IGN); + return ROFF_IGN; /* Get the custom end marker. */ @@ -1492,7 +1850,7 @@ roff_block(ROFF_ARGS) mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, ln, pos, ".%s ... %s", roffs[tok].name, cp); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -1528,8 +1886,8 @@ roff_block_sub(ROFF_ARGS) pos = i; if (roff_parse(r, buf->buf, &pos, ln, ppos) != ROFF_MAX) - return(ROFF_RERUN); - return(ROFF_IGN); + return ROFF_RERUN; + return ROFF_IGN; } } @@ -1543,11 +1901,11 @@ roff_block_sub(ROFF_ARGS) if (t != ROFF_cblock) { if (tok != ROFF_ig) roff_setstr(r, r->last->name, buf->buf + ppos, 2); - return(ROFF_IGN); + return ROFF_IGN; } assert(roffs[t].proc); - return((*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs)); + return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs); } static enum rofferr @@ -1557,7 +1915,7 @@ roff_block_text(ROFF_ARGS) if (tok != ROFF_ig) roff_setstr(r, r->last->name, buf->buf + pos, 2); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -1579,7 +1937,7 @@ roff_cond_sub(ROFF_ARGS) if ((t != ROFF_MAX) && (rr || roffs[t].flags & ROFFMAC_STRUCT)) { assert(roffs[t].proc); - return((*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs)); + return (*roffs[t].proc)(r, t, buf, ln, ppos, pos, offs); } /* @@ -1601,7 +1959,7 @@ roff_cond_sub(ROFF_ARGS) if (*ep != '\0') ++ep; } - return(rr ? ROFF_CONT : ROFF_IGN); + return rr ? ROFF_CONT : ROFF_IGN; } static enum rofferr @@ -1622,9 +1980,11 @@ roff_cond_text(ROFF_ARGS) if (*ep != '\0') ++ep; } - return(rr ? ROFF_CONT : ROFF_IGN); + return rr ? ROFF_CONT : ROFF_IGN; } +/* --- handling of numeric and conditional expressions -------------------- */ + /* * Parse a single signed integer number. Stop at the first non-digit. * If there is at least one digit, return success and advance the @@ -1669,12 +2029,10 @@ roff_getnum(const char *v, int *pos, int *res, int flags) scaled = *res * 240 / 2.54; break; case 'v': - /* FALLTROUGH */ case 'P': scaled = *res * 40; break; case 'm': - /* FALLTROUGH */ case 'n': scaled = *res * 24; break; @@ -1696,7 +2054,7 @@ roff_getnum(const char *v, int *pos, int *res, int flags) *res = scaled; *pos = p + 1; - return(1); + return 1; } /* @@ -1739,7 +2097,7 @@ out: else if (*s3 != '\0') s3++; *pos = s3 - v; - return(match); + return match; } /* @@ -1747,8 +2105,10 @@ out: * or string condition. */ static int -roff_evalcond(struct roff *r, int ln, const char *v, int *pos) +roff_evalcond(struct roff *r, int ln, char *v, int *pos) { + char *cp, *name; + size_t sz; int number, savepos, wanttrue; if ('!' == v[*pos]) { @@ -1759,43 +2119,41 @@ roff_evalcond(struct roff *r, int ln, const char *v, int *pos) switch (v[*pos]) { case '\0': - return(0); + return 0; case 'n': - /* FALLTHROUGH */ case 'o': (*pos)++; - return(wanttrue); + return wanttrue; case 'c': - /* FALLTHROUGH */ case 'd': - /* FALLTHROUGH */ case 'e': - /* FALLTHROUGH */ - case 'r': - /* FALLTHROUGH */ case 't': - /* FALLTHROUGH */ case 'v': (*pos)++; - return(!wanttrue); + return !wanttrue; + case 'r': + cp = name = v + ++*pos; + sz = roff_getname(r, &cp, ln, *pos); + *pos = cp - v; + return (sz && roff_hasregn(r, name, sz)) == wanttrue; default: break; } savepos = *pos; if (roff_evalnum(r, ln, v, pos, &number, ROFFNUM_SCALE)) - return((number > 0) == wanttrue); + return (number > 0) == wanttrue; else if (*pos == savepos) - return(roff_evalstrcond(v, pos) == wanttrue); + return roff_evalstrcond(v, pos) == wanttrue; else - return (0); + return 0; } static enum rofferr roff_line_ignore(ROFF_ARGS) { - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -1804,7 +2162,7 @@ roff_insec(ROFF_ARGS) mandoc_msg(MANDOCERR_REQ_INSEC, r->parse, ln, ppos, roffs[tok].name); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -1813,7 +2171,7 @@ roff_unsupp(ROFF_ARGS) mandoc_msg(MANDOCERR_REQ_UNSUPP, r->parse, ln, ppos, roffs[tok].name); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -1872,6 +2230,8 @@ roff_cond(ROFF_ARGS) if (buf->buf[pos] == '\\' && buf->buf[pos + 1] == '{') { r->last->endspan = -1; pos += 2; + while (buf->buf[pos] == ' ') + pos++; goto out; } @@ -1889,7 +2249,7 @@ roff_cond(ROFF_ARGS) out: *offs = pos; - return(ROFF_RERUN); + return ROFF_RERUN; } static enum rofferr @@ -1914,11 +2274,11 @@ roff_ds(ROFF_ARGS) name = string = buf->buf + pos; if (*name == '\0') - return(ROFF_IGN); + return ROFF_IGN; namesz = roff_getname(r, &string, ln, pos); if (name[namesz] == '\\') - return(ROFF_IGN); + return ROFF_IGN; /* Read past the initial double-quote, if any. */ if (*string == '"') @@ -1927,7 +2287,7 @@ roff_ds(ROFF_ARGS) /* The rest is the value. */ roff_setstrn(&r->strtab, name, namesz, string, strlen(string), ROFF_as == tok); - return(ROFF_IGN); + return ROFF_IGN; } /* @@ -1943,17 +2303,11 @@ roff_getop(const char *v, int *pos, char *res) switch (*res) { case '+': - /* FALLTHROUGH */ case '-': - /* FALLTHROUGH */ case '*': - /* FALLTHROUGH */ case '/': - /* FALLTHROUGH */ case '%': - /* FALLTHROUGH */ case '&': - /* FALLTHROUGH */ case ':': break; case '<': @@ -1993,11 +2347,11 @@ roff_getop(const char *v, int *pos, char *res) (*pos)++; break; default: - return(0); + return 0; } (*pos)++; - return(*res); + return *res; } /* @@ -2010,11 +2364,11 @@ roff_evalpar(struct roff *r, int ln, { if ('(' != v[*pos]) - return(roff_getnum(v, pos, res, flags)); + return roff_getnum(v, pos, res, flags); (*pos)++; if ( ! roff_evalnum(r, ln, v, pos, res, flags | ROFFNUM_WHITE)) - return(0); + return 0; /* * Omission of the closing parenthesis @@ -2025,9 +2379,9 @@ roff_evalpar(struct roff *r, int ln, if (')' == v[*pos]) (*pos)++; else if (NULL == res) - return(0); + return 0; - return(1); + return 1; } /* @@ -2051,7 +2405,7 @@ roff_evalnum(struct roff *r, int ln, const char *v, (*pos)++; if ( ! roff_evalpar(r, ln, v, pos, res, flags)) - return(0); + return 0; while (1) { if (flags & ROFFNUM_WHITE) @@ -2066,7 +2420,7 @@ roff_evalnum(struct roff *r, int ln, const char *v, (*pos)++; if ( ! roff_evalpar(r, ln, v, pos, &operand2, flags)) - return(0); + return 0; if (flags & ROFFNUM_WHITE) while (isspace((unsigned char)v[*pos])) @@ -2139,9 +2493,11 @@ roff_evalnum(struct roff *r, int ln, const char *v, abort(); } } - return(1); + return 1; } +/* --- register management ------------------------------------------------ */ + void roff_setreg(struct roff *r, const char *name, int val, char sign) { @@ -2178,24 +2534,26 @@ roff_setreg(struct roff *r, const char *name, int val, char sign) * were to turn up, another special value would have to be chosen. */ static int -roff_getregro(const char *name) +roff_getregro(const struct roff *r, const char *name) { switch (*name) { + case '$': /* Number of arguments of the last macro evaluated. */ + return r->argc; case 'A': /* ASCII approximation mode is always off. */ - return(0); + return 0; case 'g': /* Groff compatibility mode is always on. */ - return(1); + return 1; case 'H': /* Fixed horizontal resolution. */ - return (24); + return 24; case 'j': /* Always adjust left margin only. */ - return(0); + return 0; case 'T': /* Some output device is always defined. */ - return(1); + return 1; case 'V': /* Fixed vertical resolution. */ - return (40); + return 40; default: - return (-1); + return -1; } } @@ -2206,16 +2564,16 @@ roff_getreg(const struct roff *r, const char *name) int val; if ('.' == name[0] && '\0' != name[1] && '\0' == name[2]) { - val = roff_getregro(name + 1); + val = roff_getregro(r, name + 1); if (-1 != val) - return (val); + return val; } for (reg = r->regtab; reg; reg = reg->next) if (0 == strcmp(name, reg->key.p)) - return(reg->val); + return reg->val; - return(0); + return 0; } static int @@ -2225,17 +2583,37 @@ roff_getregn(const struct roff *r, const char *name, size_t len) int val; if ('.' == name[0] && 2 == len) { - val = roff_getregro(name + 1); + val = roff_getregro(r, name + 1); + if (-1 != val) + return val; + } + + for (reg = r->regtab; reg; reg = reg->next) + if (len == reg->key.sz && + 0 == strncmp(name, reg->key.p, len)) + return reg->val; + + return 0; +} + +static int +roff_hasregn(const struct roff *r, const char *name, size_t len) +{ + struct roffreg *reg; + int val; + + if ('.' == name[0] && 2 == len) { + val = roff_getregro(r, name + 1); if (-1 != val) - return (val); + return 1; } for (reg = r->regtab; reg; reg = reg->next) if (len == reg->key.sz && 0 == strncmp(name, reg->key.p, len)) - return(reg->val); + return 1; - return(0); + return 0; } static void @@ -2261,11 +2639,11 @@ roff_nr(ROFF_ARGS) key = val = buf->buf + pos; if (*key == '\0') - return(ROFF_IGN); + return ROFF_IGN; keysz = roff_getname(r, &val, ln, pos); if (key[keysz] == '\\') - return(ROFF_IGN); + return ROFF_IGN; key[keysz] = '\0'; sign = *val; @@ -2275,7 +2653,7 @@ roff_nr(ROFF_ARGS) if (roff_evalnum(r, ln, val, NULL, &iv, ROFFNUM_SCALE)) roff_setreg(r, key, iv, sign); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2287,7 +2665,7 @@ roff_rr(ROFF_ARGS) name = cp = buf->buf + pos; if (*name == '\0') - return(ROFF_IGN); + return ROFF_IGN; namesz = roff_getname(r, &cp, ln, pos); name[namesz] = '\0'; @@ -2303,9 +2681,11 @@ roff_rr(ROFF_ARGS) free(reg->key.p); free(reg); } - return(ROFF_IGN); + return ROFF_IGN; } +/* --- handler functions for roff requests -------------------------------- */ + static enum rofferr roff_rm(ROFF_ARGS) { @@ -2321,7 +2701,7 @@ roff_rm(ROFF_ARGS) if (name[namesz] == '\\') break; } - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2334,7 +2714,7 @@ roff_it(ROFF_ARGS) if ( ! roff_evalnum(r, ln, buf->buf, &pos, &iv, 0)) { mandoc_msg(MANDOCERR_IT_NONUM, r->parse, ln, ppos, buf->buf + 1); - return(ROFF_IGN); + return ROFF_IGN; } while (isspace((unsigned char)buf->buf[pos])) @@ -2350,7 +2730,7 @@ roff_it(ROFF_ARGS) roffit_macro = mandoc_strdup(iv != 1 || strcmp(buf->buf + pos, "an-trap") ? buf->buf + pos : "br"); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2365,7 +2745,7 @@ roff_Dd(ROFF_ARGS) if (r->format == 0) r->format = MPARSE_MDOC; - return(ROFF_CONT); + return ROFF_CONT; } static enum rofferr @@ -2380,7 +2760,7 @@ roff_TH(ROFF_ARGS) if (r->format == 0) r->format = MPARSE_MAN; - return(ROFF_CONT); + return ROFF_CONT; } static enum rofferr @@ -2394,9 +2774,9 @@ roff_TE(ROFF_ARGS) free(buf->buf); buf->buf = mandoc_strdup(".sp"); buf->sz = 4; - return(ROFF_REPARSE); + return ROFF_REPARSE; } - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2409,7 +2789,7 @@ roff_T_(ROFF_ARGS) else tbl_restart(ppos, ln, r->tbl); - return(ROFF_IGN); + return ROFF_IGN; } /* @@ -2432,7 +2812,7 @@ roff_eqndelim(struct roff *r, struct buf *buf, int pos) cp2 = strchr(cp1, r->eqn == NULL ? r->last_eqn->odelim : r->last_eqn->cdelim); if (cp2 == NULL) - return(ROFF_CONT); + return ROFF_CONT; *cp2++ = '\0'; bef_pr = bef_nl = aft_nl = aft_pr = ""; @@ -2475,7 +2855,7 @@ roff_eqndelim(struct roff *r, struct buf *buf, int pos) /* Toggle the in-line state of the eqn subsystem. */ r->eqn_inline = r->eqn == NULL; - return(ROFF_REPARSE); + return ROFF_REPARSE; } static enum rofferr @@ -2500,7 +2880,7 @@ roff_EQ(ROFF_ARGS) mandoc_vmsg(MANDOCERR_ARG_SKIP, r->parse, ln, pos, ".EQ %s", buf->buf + pos); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2508,7 +2888,7 @@ roff_EN(ROFF_ARGS) { mandoc_msg(MANDOCERR_BLK_NOTOPEN, r->parse, ln, ppos, "EN"); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2530,7 +2910,7 @@ roff_TS(ROFF_ARGS) r->first_tbl = r->last_tbl = tbl; r->tbl = r->last_tbl = tbl; - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2538,7 +2918,7 @@ roff_brp(ROFF_ARGS) { buf->buf[pos - 1] = '\0'; - return(ROFF_CONT); + return ROFF_CONT; } static enum rofferr @@ -2555,7 +2935,7 @@ roff_cc(ROFF_ARGS) mandoc_vmsg(MANDOCERR_ARG_EXCESS, r->parse, ln, p - buf->buf, "cc ... %s", p); - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2569,7 +2949,7 @@ roff_tr(ROFF_ARGS) if (*p == '\0') { mandoc_msg(MANDOCERR_REQ_EMPTY, r->parse, ln, ppos, "tr"); - return(ROFF_IGN); + return ROFF_IGN; } while (*p != '\0') { @@ -2581,7 +2961,7 @@ roff_tr(ROFF_ARGS) if (esc == ESCAPE_ERROR) { mandoc_msg(MANDOCERR_ESC_BAD, r->parse, ln, (int)(p - buf->buf), first); - return(ROFF_IGN); + return ROFF_IGN; } fsz = (size_t)(p - first); } @@ -2592,7 +2972,7 @@ roff_tr(ROFF_ARGS) if (esc == ESCAPE_ERROR) { mandoc_msg(MANDOCERR_ESC_BAD, r->parse, ln, (int)(p - buf->buf), second); - return(ROFF_IGN); + return ROFF_IGN; } ssz = (size_t)(p - second); } else if (*second == '\0') { @@ -2617,7 +2997,7 @@ roff_tr(ROFF_ARGS) r->xtab[(int)*first].sz = ssz; } - return(ROFF_IGN); + return ROFF_IGN; } static enum rofferr @@ -2643,19 +3023,21 @@ roff_so(ROFF_ARGS) free(buf->buf); buf->buf = cp; *offs = 0; - return(ROFF_REPARSE); + return ROFF_REPARSE; } *offs = pos; - return(ROFF_SO); + return ROFF_SO; } +/* --- user defined strings and macros ------------------------------------ */ + static enum rofferr roff_userdef(ROFF_ARGS) { const char *arg[9], *ap; char *cp, *n1, *n2; - int i; + int i, ib, ie; size_t asz, rsz; /* @@ -2663,10 +3045,16 @@ roff_userdef(ROFF_ARGS) * and NUL-terminate them. */ + r->argc = 0; cp = buf->buf + pos; - for (i = 0; i < 9; i++) - arg[i] = *cp == '\0' ? "" : - mandoc_getarg(r->parse, &cp, ln, &pos); + for (i = 0; i < 9; i++) { + if (*cp == '\0') + arg[i] = ""; + else { + arg[i] = mandoc_getarg(r->parse, &cp, ln, &pos); + r->argc = i + 1; + } + } /* * Expand macro arguments. @@ -2683,9 +3071,14 @@ roff_userdef(ROFF_ARGS) continue; if (*cp++ != '$') continue; - i = *cp - '1'; - if (0 > i || 8 < i) - continue; + if (*cp == '*') { /* \\$* inserts all arguments */ + ib = 0; + ie = r->argc - 1; + } else { /* \\$1 .. \\$9 insert one argument */ + ib = ie = *cp - '1'; + if (ib < 0 || ib > 8) + continue; + } cp -= 2; /* @@ -2693,11 +3086,13 @@ roff_userdef(ROFF_ARGS) * taking escaping of quotes into account. */ - asz = 0; - for (ap = arg[i]; *ap != '\0'; ap++) { - asz++; - if (*ap == '"') - asz += 3; + asz = ie > ib ? ie - ib : 0; /* for blanks */ + for (i = ib; i <= ie; i++) { + for (ap = arg[i]; *ap != '\0'; ap++) { + asz++; + if (*ap == '"') + asz += 3; + } } if (asz != 3) { @@ -2738,12 +3133,16 @@ roff_userdef(ROFF_ARGS) /* Copy the expanded argument, escaping quotes. */ n2 = cp; - for (ap = arg[i]; *ap != '\0'; ap++) { - if (*ap == '"') { - memcpy(n2, "\\(dq", 4); - n2 += 4; - } else - *n2++ = *ap; + for (i = ib; i <= ie; i++) { + for (ap = arg[i]; *ap != '\0'; ap++) { + if (*ap == '"') { + memcpy(n2, "\\(dq", 4); + n2 += 4; + } else + *n2++ = *ap; + } + if (i < ie) + *n2++ = ' '; } } @@ -2756,8 +3155,8 @@ roff_userdef(ROFF_ARGS) buf->buf = n1; *offs = 0; - return(buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ? - ROFF_REPARSE : ROFF_APPEND); + return buf->sz > 1 && buf->buf[buf->sz - 2] == '\n' ? + ROFF_REPARSE : ROFF_APPEND; } static size_t @@ -2768,7 +3167,7 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos) name = *cpp; if ('\0' == *name) - return(0); + return 0; /* Read until end of name and terminate it with NUL. */ for (cp = name; 1; cp++) { @@ -2795,7 +3194,7 @@ roff_getname(struct roff *r, char **cpp, int ln, int pos) cp++; *cpp = cp; - return(namesz); + return namesz; } /* @@ -2895,14 +3294,14 @@ roff_getstrn(const struct roff *r, const char *name, size_t len) for (n = r->strtab; n; n = n->next) if (0 == strncmp(name, n->key.p, len) && '\0' == n->key.p[(int)len]) - return(n->val.p); + return n->val.p; for (i = 0; i < PREDEFS_MAX; i++) if (0 == strncmp(name, predefs[i].name, len) && '\0' == predefs[i].name[(int)len]) - return(predefs[i].str); + return predefs[i].str; - return(NULL); + return NULL; } static void @@ -2918,18 +3317,20 @@ roff_freestr(struct roffkv *r) } } +/* --- accessors and utility functions ------------------------------------ */ + const struct tbl_span * roff_span(const struct roff *r) { - return(r->tbl ? tbl_span(r->tbl) : NULL); + return r->tbl ? tbl_span(r->tbl) : NULL; } const struct eqn * roff_eqn(const struct roff *r) { - return(r->last_eqn ? &r->last_eqn->eqn : NULL); + return r->last_eqn ? &r->last_eqn->eqn : NULL; } /* @@ -2947,9 +3348,9 @@ roff_strdup(const struct roff *r, const char *p) enum mandoc_esc esc; if (NULL == r->xmbtab && NULL == r->xtab) - return(mandoc_strdup(p)); + return mandoc_strdup(p); else if ('\0' == *p) - return(mandoc_strdup("")); + return mandoc_strdup(""); /* * Step through each character looking for term matches @@ -3021,14 +3422,14 @@ roff_strdup(const struct roff *r, const char *p) } res[(int)ssz] = '\0'; - return(res); + return res; } int roff_getformat(const struct roff *r) { - return(r->format); + return r->format; } /* @@ -3051,17 +3452,17 @@ roff_getcontrol(const struct roff *r, const char *cp, int *ppos) if (0 != r->control && cp[pos] == r->control) pos++; else if (0 != r->control) - return(0); + return 0; else if ('\\' == cp[pos] && '.' == cp[pos + 1]) pos += 2; else if ('.' == cp[pos] || '\'' == cp[pos]) pos++; else - return(0); + return 0; while (' ' == cp[pos] || '\t' == cp[pos]) pos++; *ppos = pos; - return(1); + return 1; } diff --git a/usr/src/cmd/mandoc/roff.h b/usr/src/cmd/mandoc/roff.h new file mode 100644 index 0000000000..19ec50f42e --- /dev/null +++ b/usr/src/cmd/mandoc/roff.h @@ -0,0 +1,164 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct mdoc_arg; +union mdoc_data; + +enum roff_macroset { + MACROSET_NONE = 0, + MACROSET_MDOC, + MACROSET_MAN +}; + +enum roff_sec { + SEC_NONE = 0, + SEC_NAME, + SEC_LIBRARY, + SEC_SYNOPSIS, + SEC_DESCRIPTION, + SEC_CONTEXT, + SEC_IMPLEMENTATION, /* IMPLEMENTATION NOTES */ + SEC_RETURN_VALUES, + SEC_ENVIRONMENT, + SEC_FILES, + SEC_EXIT_STATUS, + SEC_EXAMPLES, + SEC_DIAGNOSTICS, + SEC_COMPATIBILITY, + SEC_ERRORS, + SEC_SEE_ALSO, + SEC_STANDARDS, + SEC_HISTORY, + SEC_AUTHORS, + SEC_CAVEATS, + SEC_BUGS, + SEC_SECURITY, + SEC_CUSTOM, + SEC__MAX +}; + +enum roff_type { + ROFFT_ROOT, + ROFFT_BLOCK, + ROFFT_HEAD, + ROFFT_BODY, + ROFFT_TAIL, + ROFFT_ELEM, + ROFFT_TEXT, + ROFFT_TBL, + ROFFT_EQN +}; + +enum roff_next { + ROFF_NEXT_SIBLING = 0, + ROFF_NEXT_CHILD +}; + +/* + * Indicates that a BODY's formatting has ended, but + * the scope is still open. Used for badly nested blocks. + */ +enum mdoc_endbody { + ENDBODY_NOT = 0, + ENDBODY_SPACE, /* Is broken: append a space. */ + ENDBODY_NOSPACE /* Is broken: don't append a space. */ +}; + +struct roff_node { + struct roff_node *parent; /* Parent AST node. */ + struct roff_node *child; /* First child AST node. */ + struct roff_node *last; /* Last child AST node. */ + struct roff_node *next; /* Sibling AST node. */ + struct roff_node *prev; /* Prior sibling AST node. */ + struct roff_node *head; /* BLOCK */ + struct roff_node *body; /* BLOCK/ENDBODY */ + struct roff_node *tail; /* BLOCK */ + struct mdoc_arg *args; /* BLOCK/ELEM */ + union mdoc_data *norm; /* Normalized arguments. */ + char *string; /* TEXT */ + const struct tbl_span *span; /* TBL */ + const struct eqn *eqn; /* EQN */ + int line; /* Input file line number. */ + int pos; /* Input file column number. */ + int tok; /* Request or macro ID. */ +#define TOKEN_NONE (-1) /* No request or macro. */ + int flags; +#define MDOC_VALID (1 << 0) /* Has been validated. */ +#define MDOC_ENDED (1 << 1) /* Gone past body end mark. */ +#define MDOC_EOS (1 << 2) /* At sentence boundary. */ +#define MDOC_LINE (1 << 3) /* First macro/text on line. */ +#define MDOC_SYNPRETTY (1 << 4) /* SYNOPSIS-style formatting. */ +#define MDOC_BROKEN (1 << 5) /* Must validate parent when ending. */ +#define MDOC_DELIMO (1 << 6) +#define MDOC_DELIMC (1 << 7) +#define MAN_VALID MDOC_VALID +#define MAN_EOS MDOC_EOS +#define MAN_LINE MDOC_LINE + int prev_font; /* Before entering this node. */ + int aux; /* Decoded node data, type-dependent. */ + enum roff_type type; /* AST node type. */ + enum roff_sec sec; /* Current named section. */ + enum mdoc_endbody end; /* BODY */ +}; + +struct roff_meta { + char *msec; /* Manual section, usually a digit. */ + char *vol; /* Manual volume title. */ + char *os; /* Operating system. */ + char *arch; /* Machine architecture. */ + char *title; /* Manual title, usually CAPS. */ + char *name; /* Leading manual name. */ + char *date; /* Normalized date. */ + int hasbody; /* Document is not empty. */ +}; + +struct roff_man { + struct roff_meta meta; /* Document meta-data. */ + struct mparse *parse; /* Parse pointer. */ + struct roff *roff; /* Roff parser state data. */ + const char *defos; /* Default operating system. */ + struct roff_node *first; /* The first node parsed. */ + struct roff_node *last; /* The last node parsed. */ + struct roff_node *last_es; /* The most recent Es node. */ + int quick; /* Abort parse early. */ + int flags; /* Parse flags. */ +#define MDOC_LITERAL (1 << 1) /* In a literal scope. */ +#define MDOC_PBODY (1 << 2) /* In the document body. */ +#define MDOC_NEWLINE (1 << 3) /* First macro/text in a line. */ +#define MDOC_PHRASE (1 << 4) /* In a Bl -column phrase. */ +#define MDOC_PHRASELIT (1 << 5) /* Literal within a phrase. */ +#define MDOC_FREECOL (1 << 6) /* `It' invocation should close. */ +#define MDOC_SYNOPSIS (1 << 7) /* SYNOPSIS-style formatting. */ +#define MDOC_KEEP (1 << 8) /* In a word keep. */ +#define MDOC_SMOFF (1 << 9) /* Spacing is off. */ +#define MDOC_NODELIMC (1 << 10) /* Disable closing delimiter handling. */ +#define MAN_ELINE (1 << 11) /* Next-line element scope. */ +#define MAN_BLINE (1 << 12) /* Next-line block scope. */ +#define MDOC_PHRASEQF (1 << 13) /* Quote first word encountered. */ +#define MDOC_PHRASEQL (1 << 14) /* Quote last word of this phrase. */ +#define MDOC_PHRASEQN (1 << 15) /* Quote first word of the next phrase. */ +#define MAN_LITERAL MDOC_LITERAL +#define MAN_NEWLINE MDOC_NEWLINE + enum roff_macroset macroset; /* Kind of high-level macros used. */ + enum roff_sec lastsec; /* Last section seen. */ + enum roff_sec lastnamed; /* Last standard section seen. */ + enum roff_next next; /* Where to put the next node. */ +}; + + +void deroff(char **, const struct roff_node *); diff --git a/usr/src/cmd/mandoc/roff_int.h b/usr/src/cmd/mandoc/roff_int.h new file mode 100644 index 0000000000..5567b758de --- /dev/null +++ b/usr/src/cmd/mandoc/roff_int.h @@ -0,0 +1,41 @@ +/* $Id: roff_int.h,v 1.7 2015/11/07 14:01:16 schwarze Exp $ */ +/* + * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct roff_node *roff_node_alloc(struct roff_man *, int, int, + enum roff_type, int); +void roff_node_append(struct roff_man *, struct roff_node *); +void roff_word_alloc(struct roff_man *, int, int, const char *); +void roff_word_append(struct roff_man *, const char *); +void roff_elem_alloc(struct roff_man *, int, int, int); +struct roff_node *roff_block_alloc(struct roff_man *, int, int, int); +struct roff_node *roff_head_alloc(struct roff_man *, int, int, int); +struct roff_node *roff_body_alloc(struct roff_man *, int, int, int); +void roff_addeqn(struct roff_man *, const struct eqn *); +void roff_addtbl(struct roff_man *, const struct tbl_span *); +void roff_node_unlink(struct roff_man *, struct roff_node *); +void roff_node_free(struct roff_node *); +void roff_node_delete(struct roff_man *, struct roff_node *); + +/* + * Functions called from roff.c need to be declared here, + * not in libmdoc.h or libman.h, even if they are specific + * to either the mdoc(7) or the man(7) parser. + */ + +void man_breakscope(struct roff_man *, int); +void mdoc_argv_free(struct mdoc_arg *); diff --git a/usr/src/cmd/mandoc/st.c b/usr/src/cmd/mandoc/st.c index 172403ad18..02868f08d2 100644 --- a/usr/src/cmd/mandoc/st.c +++ b/usr/src/cmd/mandoc/st.c @@ -1,4 +1,4 @@ -/* $Id: st.c,v 1.11 2014/08/10 23:54:41 schwarze Exp $ */ +/* $Id: st.c,v 1.13 2015/10/06 18:32:20 schwarze Exp $ */ /* * Copyright (c) 2009 Kristaps Dzonsons <kristaps@bsd.lv> * @@ -20,6 +20,7 @@ #include <string.h> +#include "roff.h" #include "mdoc.h" #include "libmdoc.h" @@ -32,5 +33,5 @@ mdoc_a2st(const char *p) #include "st.in" - return(NULL); + return NULL; } diff --git a/usr/src/cmd/mandoc/tag.c b/usr/src/cmd/mandoc/tag.c new file mode 100644 index 0000000000..baedf15ad9 --- /dev/null +++ b/usr/src/cmd/mandoc/tag.c @@ -0,0 +1,204 @@ +/* $Id: tag.c,v 1.12 2016/07/08 20:42:15 schwarze Exp $ */ +/* + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" + +#include <sys/types.h> + +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "mandoc_aux.h" +#include "mandoc_ohash.h" +#include "tag.h" + +struct tag_entry { + size_t line; + int prio; + char s[]; +}; + +static void tag_signal(int); + +static struct ohash tag_data; +static struct tag_files tag_files; + + +/* + * Prepare for using a pager. + * Not all pagers are capable of using a tag file, + * but for simplicity, create it anyway. + */ +struct tag_files * +tag_init(void) +{ + struct sigaction sa; + int ofd; + + ofd = -1; + tag_files.tfd = -1; + tag_files.tcpgid = -1; + + /* Clean up when dying from a signal. */ + + memset(&sa, 0, sizeof(sa)); + sigfillset(&sa.sa_mask); + sa.sa_handler = tag_signal; + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + + /* + * POSIX requires that a process calling tcsetpgrp(3) + * from the background gets a SIGTTOU signal. + * In that case, do not stop. + */ + + sa.sa_handler = SIG_IGN; + sigaction(SIGTTOU, &sa, NULL); + + /* Save the original standard output for use by the pager. */ + + if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) + goto fail; + + /* Create both temporary output files. */ + + (void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX", + sizeof(tag_files.ofn)); + (void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX", + sizeof(tag_files.tfn)); + if ((ofd = mkstemp(tag_files.ofn)) == -1) + goto fail; + if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) + goto fail; + if (dup2(ofd, STDOUT_FILENO) == -1) + goto fail; + close(ofd); + + /* + * Set up the ohash table to collect output line numbers + * where various marked-up terms are documented. + */ + + mandoc_ohash_init(&tag_data, 4, offsetof(struct tag_entry, s)); + return &tag_files; + +fail: + tag_unlink(); + if (ofd != -1) + close(ofd); + if (tag_files.ofd != -1) + close(tag_files.ofd); + if (tag_files.tfd != -1) + close(tag_files.tfd); + *tag_files.ofn = '\0'; + *tag_files.tfn = '\0'; + tag_files.ofd = -1; + tag_files.tfd = -1; + return NULL; +} + +/* + * Set the line number where a term is defined, + * unless it is already defined at a higher priority. + */ +void +tag_put(const char *s, int prio, size_t line) +{ + struct tag_entry *entry; + size_t len; + unsigned int slot; + + if (tag_files.tfd <= 0 || strchr(s, ' ') != NULL) + return; + slot = ohash_qlookup(&tag_data, s); + entry = ohash_find(&tag_data, slot); + if (entry == NULL) { + len = strlen(s) + 1; + entry = mandoc_malloc(sizeof(*entry) + len); + memcpy(entry->s, s, len); + ohash_insert(&tag_data, slot, entry); + } else if (entry->prio <= prio) + return; + entry->line = line; + entry->prio = prio; +} + +/* + * Write out the tags file using the previously collected + * information and clear the ohash table while going along. + */ +void +tag_write(void) +{ + FILE *stream; + struct tag_entry *entry; + unsigned int slot; + + if (tag_files.tfd <= 0) + return; + stream = fdopen(tag_files.tfd, "w"); + entry = ohash_first(&tag_data, &slot); + while (entry != NULL) { + if (stream != NULL) + fprintf(stream, "%s %s %zu\n", + entry->s, tag_files.ofn, entry->line); + free(entry); + entry = ohash_next(&tag_data, &slot); + } + ohash_delete(&tag_data); + if (stream != NULL) + fclose(stream); +} + +void +tag_unlink(void) +{ + pid_t tc_pgid; + + if (tag_files.tcpgid != -1) { + tc_pgid = tcgetpgrp(STDIN_FILENO); + if (tc_pgid == tag_files.pager_pid || + tc_pgid == getpgid(0) || + getpgid(tc_pgid) == -1) + (void)tcsetpgrp(STDIN_FILENO, tag_files.tcpgid); + } + if (*tag_files.ofn != '\0') + unlink(tag_files.ofn); + if (*tag_files.tfn != '\0') + unlink(tag_files.tfn); +} + +static void +tag_signal(int signum) +{ + struct sigaction sa; + + tag_unlink(); + memset(&sa, 0, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sigaction(signum, &sa, NULL); + kill(getpid(), signum); + /* NOTREACHED */ + _exit(1); +} diff --git a/usr/src/cmd/mandoc/manpath.h b/usr/src/cmd/mandoc/tag.h index 728373b2cc..ab1388d798 100644 --- a/usr/src/cmd/mandoc/manpath.h +++ b/usr/src/cmd/mandoc/tag.h @@ -1,7 +1,6 @@ -/* $Id: manpath.h,v 1.7 2014/12/01 04:05:32 schwarze Exp $ */ +/* $Id: tag.h,v 1.7 2015/11/20 21:59:54 schwarze Exp $ */ /* - * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> - * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,19 +15,17 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* - * Unsorted list of unique, absolute paths to be searched for manual - * databases. - */ -struct manpaths { - size_t sz; - char **paths; +struct tag_files { + char ofn[20]; + char tfn[20]; + int ofd; + int tfd; + pid_t tcpgid; + pid_t pager_pid; }; -__BEGIN_DECLS - -void manpath_manconf(struct manpaths *, const char *); -void manpath_parse(struct manpaths *, const char *, char *, char *); -void manpath_free(struct manpaths *); -__END_DECLS +struct tag_files *tag_init(void); +void tag_put(const char *, int, size_t); +void tag_write(void); +void tag_unlink(void); diff --git a/usr/src/cmd/mandoc/tbl.c b/usr/src/cmd/mandoc/tbl.c index 00ee466125..ed6fbd876a 100644 --- a/usr/src/cmd/mandoc/tbl.c +++ b/usr/src/cmd/mandoc/tbl.c @@ -1,4 +1,4 @@ -/* $Id: tbl.c,v 1.39 2015/01/30 17:32:16 schwarze Exp $ */ +/* $Id: tbl.c,v 1.40 2015/10/06 18:32:20 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -66,7 +66,7 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos) if (*cp == ';') { tbl_option(tbl, ln, p, &pos); if (p[pos] == '\0') - return(ROFF_IGN); + return ROFF_IGN; } } @@ -75,15 +75,15 @@ tbl_read(struct tbl_node *tbl, int ln, const char *p, int pos) switch (tbl->part) { case TBL_PART_LAYOUT: tbl_layout(tbl, ln, p, pos); - return(ROFF_IGN); + return ROFF_IGN; case TBL_PART_CDATA: - return(tbl_cdata(tbl, ln, p, pos) ? ROFF_TBL : ROFF_IGN); + return tbl_cdata(tbl, ln, p, pos) ? ROFF_TBL : ROFF_IGN; default: break; } tbl_data(tbl, ln, p, pos); - return(ROFF_TBL); + return ROFF_TBL; } struct tbl_node * @@ -98,7 +98,7 @@ tbl_alloc(int pos, int line, struct mparse *parse) tbl->part = TBL_PART_OPTS; tbl->opts.tab = '\t'; tbl->opts.decimal = '.'; - return(tbl); + return tbl; } void @@ -155,7 +155,7 @@ tbl_span(struct tbl_node *tbl) : tbl->first_span; if (span) tbl->current_span = span; - return(span); + return span; } int @@ -177,7 +177,7 @@ tbl_end(struct tbl_node **tblp) if (sp == NULL) { mandoc_msg(MANDOCERR_TBLDATA_NONE, tbl->parse, tbl->line, tbl->pos, NULL); - return(0); + return 0; } - return(1); + return 1; } diff --git a/usr/src/cmd/mandoc/tbl_data.c b/usr/src/cmd/mandoc/tbl_data.c index e2be64eb81..40b756a05e 100644 --- a/usr/src/cmd/mandoc/tbl_data.c +++ b/usr/src/cmd/mandoc/tbl_data.c @@ -1,4 +1,4 @@ -/* $Id: tbl_data.c,v 1.39 2015/01/30 17:32:16 schwarze Exp $ */ +/* $Id: tbl_data.c,v 1.41 2015/10/06 18:32:20 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -132,11 +132,12 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos) if (p[pos] == tbl->opts.tab) { tbl->part = TBL_PART_DATA; pos++; - getdata(tbl, tbl->last_span, ln, p, &pos); - return(1); + while (p[pos] != '\0') + getdata(tbl, tbl->last_span, ln, p, &pos); + return 1; } else if (p[pos] == '\0') { tbl->part = TBL_PART_DATA; - return(1); + return 1; } /* Fallthrough: T} is part of a word. */ @@ -156,7 +157,7 @@ tbl_cdata(struct tbl_node *tbl, int ln, const char *p, int pos) mandoc_msg(MANDOCERR_TBLDATA_SPAN, tbl->parse, ln, pos, dat->string); - return(0); + return 0; } static struct tbl_span * @@ -177,7 +178,7 @@ newspan(struct tbl_node *tbl, int line, struct tbl_row *rp) dp->prev->next = dp; tbl->last_span = dp; - return(dp); + return dp; } void diff --git a/usr/src/cmd/mandoc/tbl_html.c b/usr/src/cmd/mandoc/tbl_html.c index e7940381d2..51c43286cb 100644 --- a/usr/src/cmd/mandoc/tbl_html.c +++ b/usr/src/cmd/mandoc/tbl_html.c @@ -1,6 +1,7 @@ -/* $Id: tbl_html.c,v 1.16 2015/01/30 17:32:16 schwarze Exp $ */ +/* $Id: tbl_html.c,v 1.18 2015/10/12 00:08:16 schwarze Exp $ */ /* * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -36,14 +37,14 @@ static size_t html_tbl_len(size_t sz, void *arg) { - return(sz); + return sz; } static size_t html_tbl_strlen(const char *p, void *arg) { - return(strlen(p)); + return strlen(p); } static void @@ -107,7 +108,6 @@ print_tbl(struct html *h, const struct tbl_span *sp) switch (sp->pos) { case TBL_SPAN_HORIZ: - /* FALLTHROUGH */ case TBL_SPAN_DHORIZ: PAIR_INIT(&tag, ATTR_COLSPAN, "0"); print_otag(h, TAG_TD, 1, &tag); diff --git a/usr/src/cmd/mandoc/tbl_layout.c b/usr/src/cmd/mandoc/tbl_layout.c index ed9acc9c0a..c0eafbddbf 100644 --- a/usr/src/cmd/mandoc/tbl_layout.c +++ b/usr/src/cmd/mandoc/tbl_layout.c @@ -1,4 +1,4 @@ -/* $Id: tbl_layout.c,v 1.38 2015/02/10 11:03:13 schwarze Exp $ */ +/* $Id: tbl_layout.c,v 1.41 2015/10/12 00:08:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -115,7 +115,6 @@ mod: ln, *pos, "m"); goto mod; case 'p': - /* FALLTHROUGH */ case 'v': if (p[*pos] == '-' || p[*pos] == '+') (*pos)++; @@ -168,17 +167,14 @@ mod: switch (p[(*pos)++]) { case '3': - /* FALLTHROUGH */ case 'B': cp->flags |= TBL_CELL_BOLD; goto mod; case '2': - /* FALLTHROUGH */ case 'I': cp->flags |= TBL_CELL_ITALIC; goto mod; case '1': - /* FALLTHROUGH */ case 'R': goto mod; default: @@ -308,6 +304,7 @@ tbl_layout(struct tbl_node *tbl, int ln, const char *p, int pos) rp->next->first == NULL) { free(rp->next); rp->next = NULL; + tbl->last_row = rp; } } return; @@ -354,5 +351,5 @@ cell_alloc(struct tbl_node *tbl, struct tbl_row *rp, enum tbl_cellt pos) if (tbl->opts.cols <= p->col) tbl->opts.cols = p->col + 1; - return(p); + return p; } diff --git a/usr/src/cmd/mandoc/tbl_opts.c b/usr/src/cmd/mandoc/tbl_opts.c index c012a3c885..f2f5942ae6 100644 --- a/usr/src/cmd/mandoc/tbl_opts.c +++ b/usr/src/cmd/mandoc/tbl_opts.c @@ -1,4 +1,4 @@ -/* $Id: tbl_opts.c,v 1.20 2015/01/28 17:32:07 schwarze Exp $ */ +/* $Id: tbl_opts.c,v 1.21 2015/09/26 00:54:04 schwarze Exp $ */ /* * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -99,7 +99,6 @@ arg(struct tbl_node *tbl, int ln, const char *p, int *pos, int key) break; default: abort(); - /* NOTREACHED */ } if (len == 0) diff --git a/usr/src/cmd/mandoc/tbl_term.c b/usr/src/cmd/mandoc/tbl_term.c index 1276776668..eceaa4b60f 100644 --- a/usr/src/cmd/mandoc/tbl_term.c +++ b/usr/src/cmd/mandoc/tbl_term.c @@ -1,4 +1,4 @@ -/* $Id: tbl_term.c,v 1.40 2015/03/06 15:48:53 schwarze Exp $ */ +/* $Id: tbl_term.c,v 1.43 2015/10/12 00:08:16 schwarze Exp $ */ /* * Copyright (c) 2009, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2011, 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -47,14 +47,14 @@ static size_t term_tbl_strlen(const char *p, void *arg) { - return(term_strlen((const struct termp *)arg, p)); + return term_strlen((const struct termp *)arg, p); } static size_t term_tbl_len(size_t sz, void *arg) { - return(term_len((const struct termp *)arg, sz)); + return term_len((const struct termp *)arg, sz); } void @@ -266,12 +266,10 @@ tbl_data(struct termp *tp, const struct tbl_opts *opts, tbl_char(tp, ASCII_NBRSP, col->width); return; case TBL_DATA_HORIZ: - /* FALLTHROUGH */ case TBL_DATA_NHORIZ: tbl_char(tp, '-', col->width); return; case TBL_DATA_NDHORIZ: - /* FALLTHROUGH */ case TBL_DATA_DHORIZ: tbl_char(tp, '=', col->width); return; @@ -287,11 +285,8 @@ tbl_data(struct termp *tp, const struct tbl_opts *opts, tbl_char(tp, '=', col->width); break; case TBL_CELL_LONG: - /* FALLTHROUGH */ case TBL_CELL_CENTRE: - /* FALLTHROUGH */ case TBL_CELL_LEFT: - /* FALLTHROUGH */ case TBL_CELL_RIGHT: tbl_literal(tp, dp, col); break; @@ -303,7 +298,6 @@ tbl_data(struct termp *tp, const struct tbl_opts *opts, break; default: abort(); - /* NOTREACHED */ } } diff --git a/usr/src/cmd/mandoc/term.c b/usr/src/cmd/mandoc/term.c index ee2af9e625..0fd8f7c019 100644 --- a/usr/src/cmd/mandoc/term.c +++ b/usr/src/cmd/mandoc/term.c @@ -1,4 +1,4 @@ -/* $Id: term.c,v 1.245 2015/03/06 13:02:43 schwarze Exp $ */ +/* $Id: term.c,v 1.257 2016/04/12 15:30:00 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2010-2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -49,7 +49,7 @@ term_free(struct termp *p) void term_begin(struct termp *p, term_margin head, - term_margin foot, const void *arg) + term_margin foot, const struct roff_meta *arg) { p->headf = head; @@ -78,6 +78,8 @@ term_end(struct termp *p) * the next column. However, if less than p->trailspace blanks, * which can be 0, 1, or 2, remain to the right margin, the line * will be broken. + * - TERMP_BRTRSP: Consider trailing whitespace significant + * when deciding whether the chunk fits or not. * - TERMP_BRIND: If the chunk does not fit and the output line has * to be broken, start the next line at the right margin instead * of at the offset. Used together with TERMP_NOBREAK for the tags @@ -158,7 +160,7 @@ term_flushln(struct termp *p) if (' ' == p->buf[j] || '\t' == p->buf[j]) break; - /* Back over the the last printed character. */ + /* Back over the last printed character. */ if (8 == p->buf[j]) { assert(j); vend -= (*p->width)(p, p->buf[j - 1]); @@ -265,6 +267,7 @@ term_flushln(struct termp *p) p->col = 0; p->overstep = 0; + p->flags &= ~(TERMP_BACKAFTER | TERMP_BACKBEFORE); if ( ! (TERMP_NOBREAK & p->flags)) { p->viscol = 0; @@ -290,6 +293,10 @@ term_flushln(struct termp *p) } else if (TERMP_DANGLE & p->flags) return; + /* Trailing whitespace is significant in some columns. */ + if (vis && vbl && (TERMP_BRTRSP & p->flags)) + vis += vbl; + /* If the column was overrun, break the line. */ if (maxvis < vis + p->trailspace * (*p->width)(p, ' ')) { (*p->endline)(p); @@ -358,7 +365,7 @@ term_fontpush(struct termp *p, enum termfont f) if (++p->fonti == p->fontsz) { p->fontsz += 8; p->fontq = mandoc_reallocarray(p->fontq, - p->fontsz, sizeof(enum termfont *)); + p->fontsz, sizeof(*p->fontq)); } p->fontq[p->fonti] = f; } @@ -417,11 +424,6 @@ term_word(struct termp *p, const char *word) while ('\0' != *word) { if ('\\' != *word) { - if (TERMP_SKIPCHAR & p->flags) { - p->flags &= ~TERMP_SKIPCHAR; - word++; - continue; - } if (TERMP_NBRWORD & p->flags) { if (' ' == *word) { encode(p, nbrsp, 1); @@ -452,12 +454,11 @@ term_word(struct termp *p, const char *word) break; case ESCAPE_SPECIAL: if (p->enc == TERMENC_ASCII) { - cp = mchars_spec2str(p->symtab, - seq, sz, &ssz); + cp = mchars_spec2str(seq, sz, &ssz); if (cp != NULL) encode(p, cp, ssz); } else { - uc = mchars_spec2cp(p->symtab, seq, sz); + uc = mchars_spec2cp(seq, sz); if (uc > 0) encode1(p, uc); } @@ -472,7 +473,6 @@ term_word(struct termp *p, const char *word) term_fontrepl(p, TERMFONT_BI); continue; case ESCAPE_FONT: - /* FALLTHROUGH */ case ESCAPE_FONTROMAN: term_fontrepl(p, TERMFONT_NONE); continue; @@ -480,13 +480,13 @@ term_word(struct termp *p, const char *word) term_fontlast(p); continue; case ESCAPE_NOSPACE: - if (TERMP_SKIPCHAR & p->flags) - p->flags &= ~TERMP_SKIPCHAR; - else if ('\0' == *word) + if (p->flags & TERMP_BACKAFTER) + p->flags &= ~TERMP_BACKAFTER; + else if (*word == '\0') p->flags |= (TERMP_NOSPACE | TERMP_NONEWLINE); continue; case ESCAPE_SKIPCHAR: - p->flags |= TERMP_SKIPCHAR; + p->flags |= TERMP_BACKAFTER; continue; case ESCAPE_OVERSTRIKE: cp = seq + sz; @@ -496,9 +496,17 @@ term_word(struct termp *p, const char *word) continue; } encode1(p, *seq++); - if (seq < cp) - encode(p, "\b", 1); + if (seq < cp) { + if (p->flags & TERMP_BACKBEFORE) + p->flags |= TERMP_BACKAFTER; + else + p->flags |= TERMP_BACKBEFORE; + } } + /* Trim trailing backspace/blank pair. */ + if (p->col > 2 && p->buf[p->col - 1] == ' ') + p->col -= 2; + continue; default: continue; } @@ -553,16 +561,19 @@ encode1(struct termp *p, int c) { enum termfont f; - if (TERMP_SKIPCHAR & p->flags) { - p->flags &= ~TERMP_SKIPCHAR; - return; - } - - if (p->col + 6 >= p->maxcols) - adjbuf(p, p->col + 6); + if (p->col + 7 >= p->maxcols) + adjbuf(p, p->col + 7); - f = p->fontq[p->fonti]; + f = (c == ASCII_HYPH || c > 127 || isgraph(c)) ? + p->fontq[p->fonti] : TERMFONT_NONE; + if (p->flags & TERMP_BACKBEFORE) { + if (p->buf[p->col - 1] == ' ') + p->col--; + else + p->buf[p->col++] = 8; + p->flags &= ~TERMP_BACKBEFORE; + } if (TERMFONT_UNDER == f || TERMFONT_BI == f) { p->buf[p->col++] = '_'; p->buf[p->col++] = 8; @@ -575,6 +586,10 @@ encode1(struct termp *p, int c) p->buf[p->col++] = 8; } p->buf[p->col++] = c; + if (p->flags & TERMP_BACKAFTER) { + p->flags |= TERMP_BACKBEFORE; + p->flags &= ~TERMP_BACKAFTER; + } } static void @@ -582,29 +597,8 @@ encode(struct termp *p, const char *word, size_t sz) { size_t i; - if (TERMP_SKIPCHAR & p->flags) { - p->flags &= ~TERMP_SKIPCHAR; - return; - } - - /* - * Encode and buffer a string of characters. If the current - * font mode is unset, buffer directly, else encode then buffer - * character by character. - */ - - if (p->fontq[p->fonti] == TERMFONT_NONE) { - if (p->col + sz >= p->maxcols) - adjbuf(p, p->col + sz); - for (i = 0; i < sz; i++) - p->buf[p->col++] = word[i]; - return; - } - - /* Pre-buffer, assuming worst-case. */ - - if (p->col + 1 + (sz * 5) >= p->maxcols) - adjbuf(p, p->col + 1 + (sz * 5)); + if (p->col + 2 + (sz * 5) >= p->maxcols) + adjbuf(p, p->col + 2 + (sz * 5)); for (i = 0; i < sz; i++) { if (ASCII_HYPH == word[i] || @@ -619,8 +613,7 @@ void term_setwidth(struct termp *p, const char *wstr) { struct roffsu su; - size_t width; - int iop; + int iop, width; iop = 0; width = 0; @@ -649,7 +642,7 @@ size_t term_len(const struct termp *p, size_t sz) { - return((*p->width)(p, ' ') * sz); + return (*p->width)(p, ' ') * sz; } static size_t @@ -658,9 +651,9 @@ cond_width(const struct termp *p, int c, int *skip) if (*skip) { (*skip) = 0; - return(0); + return 0; } else - return((*p->width)(p, c)); + return (*p->width)(p, c); } size_t @@ -706,13 +699,11 @@ term_strlen(const struct termp *p, const char *cp) break; case ESCAPE_SPECIAL: if (p->enc == TERMENC_ASCII) { - rhs = mchars_spec2str(p->symtab, - seq, ssz, &rsz); + rhs = mchars_spec2str(seq, ssz, &rsz); if (rhs != NULL) break; } else { - uc = mchars_spec2cp(p->symtab, - seq, ssz); + uc = mchars_spec2cp(seq, ssz); if (uc > 0) sz += cond_width(p, uc, &skip); } @@ -776,15 +767,13 @@ term_strlen(const struct termp *p, const char *cp) case ASCII_HYPH: sz += cond_width(p, '-', &skip); cp++; - /* FALLTHROUGH */ - case ASCII_BREAK: break; default: break; } } - return(sz); + return sz; } int @@ -816,7 +805,6 @@ term_vspan(const struct termp *p, const struct roffsu *su) r = su->scale / 12.0; break; case SCALE_EN: - /* FALLTHROUGH */ case SCALE_EM: r = su->scale * 0.6; break; @@ -825,17 +813,17 @@ term_vspan(const struct termp *p, const struct roffsu *su) break; default: abort(); - /* NOTREACHED */ } ri = r > 0.0 ? r + 0.4995 : r - 0.4995; - return(ri < 66 ? ri : 1); + return ri < 66 ? ri : 1; } +/* + * Convert a scaling width to basic units, rounding down. + */ int term_hspan(const struct termp *p, const struct roffsu *su) { - double v; - v = (*p->hspan)(p, su); - return(v > 0.0 ? v + 0.0005 : v - 0.0005); + return (*p->hspan)(p, su); } diff --git a/usr/src/cmd/mandoc/term.h b/usr/src/cmd/mandoc/term.h index b65524b610..fabc117d64 100644 --- a/usr/src/cmd/mandoc/term.h +++ b/usr/src/cmd/mandoc/term.h @@ -1,15 +1,15 @@ -/* $Id: term.h,v 1.111 2015/01/31 00:12:41 schwarze Exp $ */ +/* $Id: term.h,v 1.118 2015/11/07 14:01:16 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2011, 2012, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2011-2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -38,9 +38,10 @@ enum termfont { #define TERM_MAXMARGIN 100000 /* FIXME */ +struct roff_meta; struct termp; -typedef void (*term_margin)(struct termp *, const void *); +typedef void (*term_margin)(struct termp *, const struct roff_meta *); struct termp_tbl { int width; /* width in fixed chars */ @@ -52,6 +53,7 @@ struct termp { struct rofftbl tbl; /* table configuration */ int synopsisonly; /* print the synopsis only */ int mdocstyle; /* imitate mdoc(7) output */ + size_t line; /* Current output line number. */ size_t defindent; /* Default indent for text. */ size_t defrmargin; /* Right margin of the device. */ size_t lastrmargin; /* Right margin before the last ll. */ @@ -66,23 +68,24 @@ struct termp { int overstep; /* See termp_flushln(). */ int skipvsp; /* Vertical space to skip. */ int flags; -#define TERMP_SENTENCE (1 << 1) /* Space before a sentence. */ -#define TERMP_NOSPACE (1 << 2) /* No space before words. */ -#define TERMP_NONOSPACE (1 << 3) /* No space (no autounset). */ -#define TERMP_NBRWORD (1 << 4) /* Make next word nonbreaking. */ -#define TERMP_KEEP (1 << 5) /* Keep words together. */ -#define TERMP_PREKEEP (1 << 6) /* ...starting with the next one. */ -#define TERMP_SKIPCHAR (1 << 7) /* Skip the next character. */ +#define TERMP_SENTENCE (1 << 0) /* Space before a sentence. */ +#define TERMP_NOSPACE (1 << 1) /* No space before words. */ +#define TERMP_NONOSPACE (1 << 2) /* No space (no autounset). */ +#define TERMP_NBRWORD (1 << 3) /* Make next word nonbreaking. */ +#define TERMP_KEEP (1 << 4) /* Keep words together. */ +#define TERMP_PREKEEP (1 << 5) /* ...starting with the next one. */ +#define TERMP_BACKAFTER (1 << 6) /* Back up after next character. */ +#define TERMP_BACKBEFORE (1 << 7) /* Back up before next character. */ #define TERMP_NOBREAK (1 << 8) /* See term_flushln(). */ -#define TERMP_BRIND (1 << 9) /* See term_flushln(). */ -#define TERMP_DANGLE (1 << 10) /* See term_flushln(). */ -#define TERMP_HANG (1 << 11) /* See term_flushln(). */ -#define TERMP_NOSPLIT (1 << 12) /* Do not break line before .An. */ -#define TERMP_SPLIT (1 << 13) /* Break line before .An. */ -#define TERMP_NONEWLINE (1 << 14) /* No line break in nofill mode. */ +#define TERMP_BRTRSP (1 << 9) /* See term_flushln(). */ +#define TERMP_BRIND (1 << 10) /* See term_flushln(). */ +#define TERMP_DANGLE (1 << 11) /* See term_flushln(). */ +#define TERMP_HANG (1 << 12) /* See term_flushln(). */ +#define TERMP_NOSPLIT (1 << 13) /* Do not break line before .An. */ +#define TERMP_SPLIT (1 << 14) /* Break line before .An. */ +#define TERMP_NONEWLINE (1 << 15) /* No line break in nofill mode. */ int *buf; /* Output buffer. */ enum termenc enc; /* Type of encoding. */ - const struct mchars *symtab; /* Character table. */ enum termfont fontl; /* Last font set. */ enum termfont *fontq; /* Symmetric fonts. */ int fontsz; /* Allocated size of font stack */ @@ -94,15 +97,14 @@ struct termp { void (*end)(struct termp *); void (*endline)(struct termp *); void (*advance)(struct termp *, size_t); - void (*setwidth)(struct termp *, int, size_t); + void (*setwidth)(struct termp *, int, int); size_t (*width)(const struct termp *, int); - double (*hspan)(const struct termp *, + int (*hspan)(const struct termp *, const struct roffsu *); const void *argf; /* arg for headf/footf */ struct termp_ps *ps; }; -__BEGIN_DECLS struct tbl_span; struct eqn; @@ -117,7 +119,7 @@ void term_vspace(struct termp *); void term_word(struct termp *, const char *); void term_flushln(struct termp *); void term_begin(struct termp *, term_margin, - term_margin, const void *); + term_margin, const struct roff_meta *); void term_end(struct termp *); void term_setwidth(struct termp *, const char *); @@ -131,5 +133,3 @@ void term_fontpop(struct termp *); void term_fontpopq(struct termp *, int); void term_fontrepl(struct termp *, enum termfont); void term_fontlast(struct termp *); - -__END_DECLS diff --git a/usr/src/cmd/mandoc/term_ascii.c b/usr/src/cmd/mandoc/term_ascii.c index 4ce4b686c4..fecdb0a964 100644 --- a/usr/src/cmd/mandoc/term_ascii.c +++ b/usr/src/cmd/mandoc/term_ascii.c @@ -1,15 +1,15 @@ -/* $Id: term_ascii.c,v 1.43 2015/02/16 14:11:41 schwarze Exp $ */ +/* $Id: term_ascii.c,v 1.53 2016/07/08 22:29:05 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> - * Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> + * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -35,11 +35,11 @@ #include "mandoc_aux.h" #include "out.h" #include "term.h" +#include "manconf.h" #include "main.h" -static struct termp *ascii_init(enum termenc, - const struct mchars *, char *); -static double ascii_hspan(const struct termp *, +static struct termp *ascii_init(enum termenc, const struct manoutput *); +static int ascii_hspan(const struct termp *, const struct roffsu *); static size_t ascii_width(const struct termp *, int); static void ascii_advance(struct termp *, size_t); @@ -47,7 +47,7 @@ static void ascii_begin(struct termp *); static void ascii_end(struct termp *); static void ascii_endline(struct termp *); static void ascii_letter(struct termp *, int); -static void ascii_setwidth(struct termp *, int, size_t); +static void ascii_setwidth(struct termp *, int, int); #if HAVE_WCHAR static void locale_advance(struct termp *, size_t); @@ -58,17 +58,16 @@ static size_t locale_width(const struct termp *, int); static struct termp * -ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts) +ascii_init(enum termenc enc, const struct manoutput *outopts) { - const char *toks[5]; +#if HAVE_WCHAR char *v; +#endif struct termp *p; - const char *errstr; - int num; p = mandoc_calloc(1, sizeof(struct termp)); - p->symtab = mchars; + p->line = 1; p->tabwidth = 5; p->defrmargin = p->lastrmargin = 78; p->fontq = mandoc_reallocarray(NULL, @@ -89,8 +88,16 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts) #if HAVE_WCHAR if (TERMENC_ASCII != enc) { + + /* + * Do not change any of this to LC_ALL. It might break + * the formatting by subtly changing the behaviour of + * various functions, for example strftime(3). As a + * worst case, it might even cause buffer overflows. + */ + v = TERMENC_LOCALE == enc ? - setlocale(LC_ALL, "") : + setlocale(LC_CTYPE, "") : setlocale(LC_CTYPE, "en_US.UTF-8"); if (NULL != v && MB_CUR_MAX > 1) { p->enc = enc; @@ -102,77 +109,52 @@ ascii_init(enum termenc enc, const struct mchars *mchars, char *outopts) } #endif - toks[0] = "indent"; - toks[1] = "width"; - toks[2] = "mdoc"; - toks[3] = "synopsis"; - toks[4] = NULL; - - while (outopts && *outopts) - switch (getsubopt(&outopts, UNCONST(toks), &v)) { - case 0: - num = strtonum(v, 0, 1000, &errstr); - if (!errstr) - p->defindent = num; - break; - case 1: - num = strtonum(v, 0, 1000, &errstr); - if (!errstr) - p->defrmargin = num; - break; - case 2: - /* - * Temporary, undocumented mode - * to imitate mdoc(7) output style. - */ - p->mdocstyle = 1; - p->defindent = 5; - break; - case 3: - p->synopsisonly = 1; - break; - default: - break; - } - - /* Enforce a lower boundary. */ - if (p->defrmargin < 58) - p->defrmargin = 58; - - return(p); + if (outopts->mdoc) { + p->mdocstyle = 1; + p->defindent = 5; + } + if (outopts->indent) + p->defindent = outopts->indent; + if (outopts->width) + p->defrmargin = outopts->width; + if (outopts->synopsisonly) + p->synopsisonly = 1; + + return p; } void * -ascii_alloc(const struct mchars *mchars, char *outopts) +ascii_alloc(const struct manoutput *outopts) { - return(ascii_init(TERMENC_ASCII, mchars, outopts)); + return ascii_init(TERMENC_ASCII, outopts); } void * -utf8_alloc(const struct mchars *mchars, char *outopts) +utf8_alloc(const struct manoutput *outopts) { - return(ascii_init(TERMENC_UTF8, mchars, outopts)); + return ascii_init(TERMENC_UTF8, outopts); } void * -locale_alloc(const struct mchars *mchars, char *outopts) +locale_alloc(const struct manoutput *outopts) { - return(ascii_init(TERMENC_LOCALE, mchars, outopts)); + return ascii_init(TERMENC_LOCALE, outopts); } static void -ascii_setwidth(struct termp *p, int iop, size_t width) +ascii_setwidth(struct termp *p, int iop, int width) { + width /= 24; p->rmargin = p->defrmargin; if (iop > 0) p->defrmargin += width; else if (iop == 0) - p->defrmargin = width ? width : p->lastrmargin; - else if (p->defrmargin > width) + p->defrmargin = width ? (size_t)width : p->lastrmargin; + else if (p->defrmargin > (size_t)width) p->defrmargin -= width; else p->defrmargin = 0; @@ -181,24 +163,24 @@ ascii_setwidth(struct termp *p, int iop, size_t width) } void -ascii_sepline(void *arg) +terminal_sepline(void *arg) { struct termp *p; size_t i; p = (struct termp *)arg; - putchar('\n'); + (*p->endline)(p); for (i = 0; i < p->defrmargin; i++) - putchar('-'); - putchar('\n'); - putchar('\n'); + (*p->letter)(p, '-'); + (*p->endline)(p); + (*p->endline)(p); } static size_t ascii_width(const struct termp *p, int c) { - return(1); + return 1; } void @@ -233,6 +215,7 @@ static void ascii_endline(struct termp *p) { + p->line++; putchar('\n'); } @@ -245,52 +228,42 @@ ascii_advance(struct termp *p, size_t len) putchar(' '); } -static double +static int ascii_hspan(const struct termp *p, const struct roffsu *su) { double r; - /* - * Approximate based on character width. - * None of these will be actually correct given that an inch on - * the screen depends on character size, terminal, etc., etc. - */ switch (su->unit) { case SCALE_BU: - r = su->scale * 10.0 / 240.0; + r = su->scale; break; case SCALE_CM: - r = su->scale * 10.0 / 2.54; + r = su->scale * 240.0 / 2.54; break; case SCALE_FS: - r = su->scale * 2730.666; + r = su->scale * 65536.0; break; case SCALE_IN: - r = su->scale * 10.0; + r = su->scale * 240.0; break; case SCALE_MM: - r = su->scale / 100.0; + r = su->scale * 0.24; break; + case SCALE_VS: case SCALE_PC: - r = su->scale * 10.0 / 6.0; + r = su->scale * 40.0; break; case SCALE_PT: - r = su->scale * 10.0 / 72.0; - break; - case SCALE_VS: - r = su->scale * 2.0 - 1.0; + r = su->scale * 10.0 / 3.0; break; case SCALE_EN: - /* FALLTHROUGH */ case SCALE_EM: - r = su->scale; + r = su->scale * 24.0; break; default: abort(); - /* NOTREACHED */ } - - return(r); + return r > 0.0 ? r + 0.01 : r - 0.01; } const char * @@ -365,8 +338,8 @@ ascii_uc2str(int uc) assert(uc >= 0); if ((size_t)uc < sizeof(tab)/sizeof(tab[0])) - return(tab[uc]); - return(mchars_uc2str(uc)); + return tab[uc]; + return mchars_uc2str(uc); } #if HAVE_WCHAR @@ -380,7 +353,7 @@ locale_width(const struct termp *p, int c) rc = wcwidth(c); if (rc < 0) rc = 0; - return(rc); + return rc; } static void @@ -396,6 +369,7 @@ static void locale_endline(struct termp *p) { + p->line++; putwchar(L'\n'); } diff --git a/usr/src/cmd/mandoc/term_ps.c b/usr/src/cmd/mandoc/term_ps.c index 12ca7d6716..6105d5589f 100644 --- a/usr/src/cmd/mandoc/term_ps.c +++ b/usr/src/cmd/mandoc/term_ps.c @@ -1,4 +1,4 @@ -/* $Id: term_ps.c,v 1.72 2015/01/21 19:40:54 schwarze Exp $ */ +/* $Id: term_ps.c,v 1.80 2015/12/23 20:50:13 schwarze Exp $ */ /* * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -20,6 +20,9 @@ #include <sys/types.h> #include <assert.h> +#if HAVE_ERR +#include <err.h> +#endif #include <stdarg.h> #include <stdint.h> #include <stdio.h> @@ -30,6 +33,7 @@ #include "mandoc_aux.h" #include "out.h" #include "term.h" +#include "manconf.h" #include "main.h" /* These work the buffer used by the header and footer. */ @@ -86,7 +90,7 @@ struct termp_ps { size_t pdfobjsz; /* size of pdfobjs */ }; -static double ps_hspan(const struct termp *, +static int ps_hspan(const struct termp *, const struct roffsu *); static size_t ps_width(const struct termp *, int); static void ps_advance(struct termp *, size_t); @@ -105,8 +109,8 @@ __attribute__((__format__ (__printf__, 2, 3))) static void ps_printf(struct termp *, const char *, ...); static void ps_putchar(struct termp *, char); static void ps_setfont(struct termp *, enum termfont); -static void ps_setwidth(struct termp *, int, size_t); -static struct termp *pspdf_alloc(const struct mchars *, char *); +static void ps_setwidth(struct termp *, int, int); +static struct termp *pspdf_alloc(const struct manoutput *); static void pdf_obj(struct termp *, size_t); /* @@ -507,39 +511,36 @@ static const struct font fonts[TERMFONT__MAX] = { }; void * -pdf_alloc(const struct mchars *mchars, char *outopts) +pdf_alloc(const struct manoutput *outopts) { struct termp *p; - if (NULL != (p = pspdf_alloc(mchars, outopts))) + if (NULL != (p = pspdf_alloc(outopts))) p->type = TERMTYPE_PDF; - return(p); + return p; } void * -ps_alloc(const struct mchars *mchars, char *outopts) +ps_alloc(const struct manoutput *outopts) { struct termp *p; - if (NULL != (p = pspdf_alloc(mchars, outopts))) + if (NULL != (p = pspdf_alloc(outopts))) p->type = TERMTYPE_PS; - return(p); + return p; } static struct termp * -pspdf_alloc(const struct mchars *mchars, char *outopts) +pspdf_alloc(const struct manoutput *outopts) { struct termp *p; unsigned int pagex, pagey; size_t marginx, marginy, lineheight; - const char *toks[2]; const char *pp; - char *v; p = mandoc_calloc(1, sizeof(struct termp)); - p->symtab = mchars; p->enc = TERMENC_ASCII; p->fontq = mandoc_reallocarray(NULL, (p->fontsz = 8), sizeof(enum termfont)); @@ -555,20 +556,6 @@ pspdf_alloc(const struct mchars *mchars, char *outopts) p->setwidth = ps_setwidth; p->width = ps_width; - toks[0] = "paper"; - toks[1] = NULL; - - pp = NULL; - - while (outopts && *outopts) - switch (getsubopt(&outopts, UNCONST(toks), &v)) { - case 0: - pp = v; - break; - default: - break; - } - /* Default to US letter (millimetres). */ pagex = 216; @@ -581,6 +568,7 @@ pspdf_alloc(const struct mchars *mchars, char *outopts) * only happens once, I'm not terribly concerned. */ + pp = outopts->paper; if (pp && strcasecmp(pp, "letter")) { if (0 == strcasecmp(pp, "a3")) { pagex = 297; @@ -595,7 +583,7 @@ pspdf_alloc(const struct mchars *mchars, char *outopts) pagex = 216; pagey = 356; } else if (2 != sscanf(pp, "%ux%u", &pagex, &pagey)) - fprintf(stderr, "%s: Unknown paper\n", pp); + warnx("%s: Unknown paper", pp); } /* @@ -629,11 +617,11 @@ pspdf_alloc(const struct mchars *mchars, char *outopts) p->ps->lineheight = lineheight; p->defrmargin = pagex - (marginx * 2); - return(p); + return p; } static void -ps_setwidth(struct termp *p, int iop, size_t width) +ps_setwidth(struct termp *p, int iop, int width) { size_t lastwidth; @@ -641,8 +629,8 @@ ps_setwidth(struct termp *p, int iop, size_t width) if (iop > 0) p->ps->width += width; else if (iop == 0) - p->ps->width = width ? width : p->ps->lastwidth; - else if (p->ps->width > width) + p->ps->width = width ? (size_t)width : p->ps->lastwidth; + else if (p->ps->width > (size_t)width) p->ps->width -= width; else p->ps->width = 0; @@ -656,10 +644,8 @@ pspdf_free(void *arg) p = (struct termp *)arg; - if (p->ps->psmarg) - free(p->ps->psmarg); - if (p->ps->pdfobjs) - free(p->ps->pdfobjs); + free(p->ps->psmarg); + free(p->ps->pdfobjs); free(p->ps); term_free(p); @@ -998,9 +984,7 @@ ps_pletter(struct termp *p, int c) switch (c) { case '(': - /* FALLTHROUGH */ case ')': - /* FALLTHROUGH */ case '\\': ps_putchar(p, '\\'); break; @@ -1283,10 +1267,10 @@ ps_width(const struct termp *p, int c) else c -= 32; - return((size_t)fonts[(int)TERMFONT_NONE].gly[c].wx); + return (size_t)fonts[(int)TERMFONT_NONE].gly[c].wx; } -static double +static int ps_hspan(const struct termp *p, const struct roffsu *su) { double r; @@ -1338,7 +1322,7 @@ ps_hspan(const struct termp *p, const struct roffsu *su) break; } - return(r); + return r * 24.0; } static void diff --git a/usr/src/cmd/mandoc/tree.c b/usr/src/cmd/mandoc/tree.c index a5a7f2c7d2..52ca7547f4 100644 --- a/usr/src/cmd/mandoc/tree.c +++ b/usr/src/cmd/mandoc/tree.c @@ -1,4 +1,4 @@ -/* $Id: tree.c,v 1.62 2015/02/05 00:14:13 schwarze Exp $ */ +/* $Id: tree.c,v 1.69 2015/10/12 00:08:16 schwarze Exp $ */ /* * Copyright (c) 2008, 2009, 2011, 2014 Kristaps Dzonsons <kristaps@bsd.lv> * Copyright (c) 2013, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -7,9 +7,9 @@ * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF @@ -26,32 +26,33 @@ #include <time.h> #include "mandoc.h" +#include "roff.h" #include "mdoc.h" #include "man.h" #include "main.h" static void print_box(const struct eqn_box *, int); -static void print_man(const struct man_node *, int); -static void print_mdoc(const struct mdoc_node *, int); +static void print_man(const struct roff_node *, int); +static void print_mdoc(const struct roff_node *, int); static void print_span(const struct tbl_span *, int); void -tree_mdoc(void *arg, const struct mdoc *mdoc) +tree_mdoc(void *arg, const struct roff_man *mdoc) { - print_mdoc(mdoc_node(mdoc)->child, 0); + print_mdoc(mdoc->first->child, 0); } void -tree_man(void *arg, const struct man *man) +tree_man(void *arg, const struct roff_man *man) { - print_man(man_node(man)->child, 0); + print_man(man->first->child, 0); } static void -print_mdoc(const struct mdoc_node *n, int indent) +print_mdoc(const struct roff_node *n, int indent) { const char *p, *t; int i, j; @@ -66,78 +67,76 @@ print_mdoc(const struct mdoc_node *n, int indent) t = p = NULL; switch (n->type) { - case MDOC_ROOT: + case ROFFT_ROOT: t = "root"; break; - case MDOC_BLOCK: + case ROFFT_BLOCK: t = "block"; break; - case MDOC_HEAD: - t = "block-head"; + case ROFFT_HEAD: + t = "head"; break; - case MDOC_BODY: + case ROFFT_BODY: if (n->end) t = "body-end"; else - t = "block-body"; + t = "body"; break; - case MDOC_TAIL: - t = "block-tail"; + case ROFFT_TAIL: + t = "tail"; break; - case MDOC_ELEM: + case ROFFT_ELEM: t = "elem"; break; - case MDOC_TEXT: + case ROFFT_TEXT: t = "text"; break; - case MDOC_TBL: + case ROFFT_TBL: break; - case MDOC_EQN: + case ROFFT_EQN: t = "eqn"; break; default: abort(); - /* NOTREACHED */ } switch (n->type) { - case MDOC_TEXT: + case ROFFT_TEXT: p = n->string; break; - case MDOC_BODY: + case ROFFT_BODY: p = mdoc_macronames[n->tok]; break; - case MDOC_HEAD: + case ROFFT_HEAD: p = mdoc_macronames[n->tok]; break; - case MDOC_TAIL: + case ROFFT_TAIL: p = mdoc_macronames[n->tok]; break; - case MDOC_ELEM: + case ROFFT_ELEM: p = mdoc_macronames[n->tok]; if (n->args) { argv = n->args->argv; argc = n->args->argc; } break; - case MDOC_BLOCK: + case ROFFT_BLOCK: p = mdoc_macronames[n->tok]; if (n->args) { argv = n->args->argv; argc = n->args->argc; } break; - case MDOC_TBL: + case ROFFT_TBL: break; - case MDOC_EQN: + case ROFFT_EQN: p = "EQ"; break; - case MDOC_ROOT: + case ROFFT_ROOT: p = "root"; break; default: abort(); - /* NOTREACHED */ } if (n->span) { @@ -160,22 +159,29 @@ print_mdoc(const struct mdoc_node *n, int indent) } putchar(' '); + if (MDOC_DELIMO & n->flags) + putchar('('); if (MDOC_LINE & n->flags) putchar('*'); - printf("%d:%d\n", n->line, n->pos + 1); + printf("%d:%d", n->line, n->pos + 1); + if (MDOC_DELIMC & n->flags) + putchar(')'); + if (MDOC_EOS & n->flags) + putchar('.'); + putchar('\n'); } if (n->eqn) print_box(n->eqn->root->first, indent + 4); if (n->child) print_mdoc(n->child, indent + - (n->type == MDOC_BLOCK ? 2 : 4)); + (n->type == ROFFT_BLOCK ? 2 : 4)); if (n->next) print_mdoc(n->next, indent); } static void -print_man(const struct man_node *n, int indent) +print_man(const struct roff_node *n, int indent) { const char *p, *t; int i; @@ -186,58 +192,53 @@ print_man(const struct man_node *n, int indent) t = p = NULL; switch (n->type) { - case MAN_ROOT: + case ROFFT_ROOT: t = "root"; break; - case MAN_ELEM: + case ROFFT_ELEM: t = "elem"; break; - case MAN_TEXT: + case ROFFT_TEXT: t = "text"; break; - case MAN_BLOCK: + case ROFFT_BLOCK: t = "block"; break; - case MAN_HEAD: - t = "block-head"; + case ROFFT_HEAD: + t = "head"; break; - case MAN_BODY: - t = "block-body"; + case ROFFT_BODY: + t = "body"; break; - case MAN_TBL: + case ROFFT_TBL: break; - case MAN_EQN: + case ROFFT_EQN: t = "eqn"; break; default: abort(); - /* NOTREACHED */ } switch (n->type) { - case MAN_TEXT: + case ROFFT_TEXT: p = n->string; break; - case MAN_ELEM: - /* FALLTHROUGH */ - case MAN_BLOCK: - /* FALLTHROUGH */ - case MAN_HEAD: - /* FALLTHROUGH */ - case MAN_BODY: + case ROFFT_ELEM: + case ROFFT_BLOCK: + case ROFFT_HEAD: + case ROFFT_BODY: p = man_macronames[n->tok]; break; - case MAN_ROOT: + case ROFFT_ROOT: p = "root"; break; - case MAN_TBL: + case ROFFT_TBL: break; - case MAN_EQN: + case ROFFT_EQN: p = "EQ"; break; default: abort(); - /* NOTREACHED */ } if (n->span) { @@ -249,14 +250,17 @@ print_man(const struct man_node *n, int indent) printf("%s (%s) ", p, t); if (MAN_LINE & n->flags) putchar('*'); - printf("%d:%d\n", n->line, n->pos + 1); + printf("%d:%d", n->line, n->pos + 1); + if (MAN_EOS & n->flags) + putchar('.'); + putchar('\n'); } if (n->eqn) print_box(n->eqn->root->first, indent + 4); if (n->child) print_man(n->child, indent + - (n->type == MAN_BLOCK ? 2 : 4)); + (n->type == ROFFT_BLOCK ? 2 : 4)); if (n->next) print_man(n->next, indent); } @@ -350,12 +354,10 @@ print_span(const struct tbl_span *sp, int indent) for (dp = sp->first; dp; dp = dp->next) { switch (dp->pos) { case TBL_DATA_HORIZ: - /* FALLTHROUGH */ case TBL_DATA_NHORIZ: putchar('-'); continue; case TBL_DATA_DHORIZ: - /* FALLTHROUGH */ case TBL_DATA_NDHORIZ: putchar('='); continue; diff --git a/usr/src/man/man1/mandoc.1 b/usr/src/man/man1/mandoc.1 index 9654a08bd0..d66d47a491 100644 --- a/usr/src/man/man1/mandoc.1 +++ b/usr/src/man/man1/mandoc.1 @@ -1,4 +1,4 @@ -.\" $Id: mandoc.1,v 1.155 2015/02/23 13:31:03 schwarze Exp $ +.\" $Id: mandoc.1,v 1.164 2015/11/05 17:47:51 schwarze Exp $ .\" .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2012, 2014, 2015 Ingo Schwarze <schwarze@openbsd.org> @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 9 2016 $ +.Dd $Mdocdate: November 5 2015 $ .Dt MANDOC 1 .Os .Sh NAME @@ -24,14 +24,12 @@ .Sh SYNOPSIS .Nm mandoc .Op Fl acfhkl -.Sm off -.Op Fl I Cm os Li = Ar name -.Sm on -.Op Fl K Ns Ar encoding +.Op Fl I Cm os Ns = Ns Ar name +.Op Fl K Ar encoding .Op Fl m Ns Ar format -.Op Fl O Ns Ar option -.Op Fl T Ns Ar output -.Op Fl W Ns Ar level +.Op Fl O Ar option +.Op Fl T Ar output +.Op Fl W Ar level .Op Ar .Sh DESCRIPTION The @@ -49,7 +47,7 @@ or text from stdin, implying .Fl m Ns Cm andoc , and produces -.Fl T Ns Cm locale +.Fl T Cm locale output. .Pp The options are as follows: @@ -77,9 +75,7 @@ This overrides any earlier and .Fl l options. -.Sm off -.It Fl I Cm os Li = Ar name -.Sm on +.It Fl I Cm os Ns = Ns Ar name Override the default operating system .Ar name for the @@ -93,7 +89,7 @@ macro. Display only the SYNOPSIS lines. Implies .Fl c . -.It Fl K Ns Ar encoding +.It Fl K Ar encoding Specify the input encoding. The supported .Ar encoding @@ -128,16 +124,16 @@ See for available formats. Defaults to .Fl m Ns Cm andoc . -.It Fl O Ns Ar option +.It Fl O Ar option Comma-separated output options. -.It Fl T Ns Ar output +.It Fl T Ar output Output format. See .Sx Output Formats for available formats. Defaults to -.Fl T Ns Cm locale . -.It Fl W Ns Ar level +.Fl T Cm locale . +.It Fl W Ar level Specify the minimum message .Ar level to be reported on the standard error output and to affect the exit status. @@ -161,7 +157,7 @@ and for details. .Pp The special option -.Fl W Ns Cm stop +.Fl W Cm stop tells .Nm to exit after parsing a file that causes warnings or errors of at least @@ -172,7 +168,7 @@ If both a and .Cm stop are requested, they can be joined with a comma, for example -.Fl W Ns Cm error , Ns Cm stop . +.Fl W Cm error , Ns Cm stop . .It Ar file Read input from zero or more files. If unspecified, reads from stdin. @@ -229,54 +225,54 @@ The utility accepts the following .Fl T arguments, which correspond to output modes: -.Bl -tag -width "-Tlocale" -.It Fl T Ns Cm ascii +.Bl -tag -width "-T locale" +.It Fl T Cm ascii Produce 7-bit ASCII output. See .Sx ASCII Output . -.It Fl T Ns Cm html +.It Fl T Cm html Produce HTML5, CSS1, and MathML output. See .Sx HTML Output . .It Fl T Ns Cm lint Parse only: produce no output. Implies -.Fl W Ns Cm warning . -.It Fl T Ns Cm locale +.Fl W Cm warning . +.It Fl T Cm locale Encode output using the current locale. This is the default. See .Sx Locale Output . -.It Fl T Ns Cm man +.It Fl T Cm man Produce .Xr man 5 format output. See .Sx Man Output . -.It Fl T Ns Cm pdf +.It Fl T Cm pdf Produce PDF output. See .Sx PDF Output . -.It Fl T Ns Cm ps +.It Fl T Cm ps Produce PostScript output. See .Sx PostScript Output . -.It Fl T Ns Cm tree +.It Fl T Cm tree Produce an indented parse tree. -.It Fl T Ns Cm utf8 +.It Fl T Cm utf8 Encode output in the UTF\-8 multi-byte format. See .Sx UTF\-8 Output . -.It Fl T Ns Cm xhtml +.It Fl T Cm xhtml This is a synonym for -.Fl T Ns Cm html . +.Fl T Cm html . .El .Pp If multiple input files are specified, these will be processed by the corresponding filter in-order. .Ss ASCII Output Output produced by -.Fl T Ns Cm ascii +.Fl T Cm ascii is rendered in standard 7-bit ASCII documented in .Xr ascii 5 . .Pp @@ -318,7 +314,7 @@ which will normalise to \(>=58. .El .Ss HTML Output Output produced by -.Fl T Ns Cm html +.Fl T Cm html conforms to HTML5 using optional self-closing tags. Default styles use only CSS1. Equations rendered from @@ -326,11 +322,11 @@ Equations rendered from blocks use MathML. .Pp The -.Pa example.style.css +.Pa mandoc.css file documents style-sheet classes available for customising output. If a style-sheet is not specified with -.Fl O Ns Ar style , -.Fl T Ns Cm html +.Fl O Cm style , +.Fl T Cm html defaults to simple output (via an embedded style-sheet) readable in any graphical or text-based web browser. @@ -386,7 +382,7 @@ relative URI. .El .Ss Locale Output Locale-depending output encoding is triggered with -.Fl T Ns Cm locale . +.Fl T Cm locale . This is the default. .Ss Man Output Translate input format into @@ -414,7 +410,7 @@ level controls which are displayed before copying the input to the output. .Ss PDF Output PDF-1.1 output may be generated by -.Fl T Ns Cm pdf . +.Fl T Cm pdf . See .Sx PostScript Output for @@ -424,7 +420,7 @@ arguments and defaults. PostScript .Qq Adobe-3.0 Level-2 pages may be generated by -.Fl T Ns Cm ps . +.Fl T Cm ps . Output pages default to letter sized and are rendered in the Times font family, 11-point. Margins are calculated as 1/9 the page length and width. @@ -456,11 +452,50 @@ is used. .El .Ss UTF\-8 Output Use -.Fl T Ns Cm utf8 +.Fl T Cm utf8 to force a UTF\-8 locale. See .Sx Locale Output for details and options. +.Ss Syntax tree output +Use +.Fl T Cm tree +to show a human readable representation of the syntax tree. +It is useful for debugging the source code of manual pages. +The exact format is subject to change, so don't write parsers for it. +Each output line shows one syntax tree node. +Child nodes are indented with respect to their parent node. +The columns are: +.Pp +.Bl -enum -compact +.It +For macro nodes, the macro name; for text and +.Xr tbl 5 +nodes, the content. +There is a special format for +.Xr eqn 5 +nodes. +.It +Node type (text, elem, block, head, body, body-end, tail, tbl, eqn). +.It +Flags: +.Bl -dash -compact +.It +An opening parenthesis if the node is an opening delimiter. +.It +An asterisk if the node starts a new input line. +.It +The input line number (starting at one). +.It +A colon. +.It +The input column number (starting at one). +.It +A closing parenthesis if the node is a closing delimiter. +.It +A full stop if the node ends a sentence. +.El +.El .Sh EXIT STATUS The .Nm @@ -477,21 +512,21 @@ they were lower than the requested .Ar level . .It 2 At least one warning occurred, but no error, and -.Fl W Ns Cm warning +.Fl W Cm warning was specified. .It 3 At least one parsing error occurred, but no unsupported feature was encountered, and -.Fl W Ns Cm error +.Fl W Cm error or -.Fl W Ns Cm warning +.Fl W Cm warning was specified. .It 4 At least one unsupported feature was encountered, and -.Fl W Ns Cm unsupp , -.Fl W Ns Cm error +.Fl W Cm unsupp , +.Fl W Cm error or -.Fl W Ns Cm warning +.Fl W Cm warning was specified. .It 5 Invalid command line arguments were specified. @@ -505,28 +540,28 @@ to exit at once, possibly in the middle of parsing or formatting a file. .El .Pp Note that selecting -.Fl T Ns Cm lint +.Fl T Cm lint output mode implies -.Fl W Ns Cm warning . +.Fl W Cm warning . .Sh EXAMPLES To page manuals to the terminal: .Pp -.Dl $ mandoc \-Wall,stop mandoc.1 2\*(Gt&1 | less +.Dl $ mandoc \-W all,stop mandoc.1 2\*(Gt&1 | less .Dl $ mandoc mandoc.1 mdoc.3 mdoc.5 | less .Pp To produce HTML manuals with -.Ar style.css +.Pa mandoc.css as the style-sheet: .Pp -.Dl $ mandoc \-Thtml -Ostyle=style.css mdoc.5 \*(Gt mdoc.5.html +.Dl $ mandoc \-T html -Ostyle=mandoc.css mdoc.5 \*(Gt mdoc.5.html .Pp To check over a large set of manuals: .Pp -.Dl $ mandoc \-Tlint `find /usr/src -name \e*\e.[1-9]` +.Dl $ mandoc \-T lint \(gafind /usr/src -name \e*\e.[1-9]\(ga .Pp To produce a series of PostScript manuals for A4 paper: .Pp -.Dl $ mandoc \-Tps \-Opaper=a4 mdoc.5 man.5 \*(Gt manuals.ps +.Dl $ mandoc \-T ps \-O paper=a4 mdoc.5 man.5 \*(Gt manuals.ps .Pp Convert a modern .Xr mdoc 5 @@ -536,7 +571,7 @@ format, for use on systems lacking an .Xr mdoc 5 parser: .Pp -.Dl $ mandoc \-Tman foo.mdoc \*(Gt foo.man +.Dl $ mandoc \-T man foo.mdoc \*(Gt foo.man .Sh DIAGNOSTICS Messages displayed by .Nm @@ -603,7 +638,7 @@ levels except those about non-existent or unreadable input files are hidden unless their level, or a lower level, is requested using a .Fl W option or -.Fl T Ns Cm lint +.Fl T Cm lint output mode. .Ss Warnings related to the document prologue .Bl -ohang @@ -889,13 +924,6 @@ list block contains text or macros before the first .Ic \&It macro. The offending children are moved before the beginning of the list. -.It Sy ".Vt block has child macro" -.Pq mdoc -The -.Ic \&Vt -macro supports plain text arguments only. -Formatting may be ugly and semantic searching -for the affected content might not work. .It Sy "fill mode already enabled, skipping" .Pq man A @@ -1521,6 +1549,13 @@ By requesting the inclusion of a sensitive file, a malicious document might otherwise trick a privileged user into inadvertently displaying the file on the screen, revealing the file content to bystanders. The argument is ignored including the file name following it. +.It Sy "skipping display without arguments" +.Pq mdoc +A +.Ic \&Bd +block macro does not have any arguments. +The block is discarded, and the block content is displayed in +whatever mode was active before the block. .It Sy "missing list type, using -item" .Pq mdoc A @@ -1717,6 +1752,7 @@ as if they were a text line. .Xr mdoc 5 , .Xr tbl 5 .Sh AUTHORS +.An -nosplit The .Nm utility was written by @@ -1725,10 +1761,10 @@ and is maintained by .An Ingo Schwarze Aq Mt schwarze@openbsd.org . .Sh BUGS In -.Fl T Ns Cm html , +.Fl T Cm html , the maximum size of an element attribute is determined by .Dv BUFSIZ , which is usually 1024 bytes. Be aware of this when setting long link formats such as -.Fl O Ns Cm style Ns = Ns Ar really/long/link . +.Fl O Cm style Ns = Ns Ar really/long/link . diff --git a/usr/src/man/man3c/ffs.3c b/usr/src/man/man3c/ffs.3c index 2e59b005b0..2197f9e106 100644 --- a/usr/src/man/man3c/ffs.3c +++ b/usr/src/man/man3c/ffs.3c @@ -31,7 +31,7 @@ ffs \- find first set bit .SH DESCRIPTION .LP -The \fBffs()\fR, \fBffsl()\, and \fBffsll()\fR functions finds the first bit set +The \fBffs()\fR, \fBffsl()\fR, and \fBffsll()\fR functions finds the first bit set (beginning with the least significant bit) and return the index of that bit. Bits are numbered starting at one (the least significant bit). .sp diff --git a/usr/src/man/man4/ike.config.4 b/usr/src/man/man4/ike.config.4 index c8ff71888a..f6634a9757 100644 --- a/usr/src/man/man4/ike.config.4 +++ b/usr/src/man/man4/ike.config.4 @@ -139,7 +139,7 @@ An IKE phase 1 identity type. IKE phase 1 identity types include: .RS 4n A quoted string. .sp -Examples include:\fB"Label foo"\fR, or \fB"C=US, OU=Sun Microsystems\\, Inc., +Examples include:\fB"Label foo"\fR, or \fB"C=US, OU=Sun Microsystems\e, Inc., N=olemcd@eng.example.com"\fR .sp A backslash (\fB\e\fR) is an escape character. If the string needs an actual diff --git a/usr/src/man/man4/rcmscript.4 b/usr/src/man/man4/rcmscript.4 index 86a14113fb..bf88dc894d 100644 --- a/usr/src/man/man4/rcmscript.4 +++ b/usr/src/man/man4/rcmscript.4 @@ -44,7 +44,6 @@ Coordination Manager .fi .SH DESCRIPTION -.sp .LP Reconfiguration and Coordination Manager (RCM) is a framework designed to coordinate device consumers during Solaris Dynamic Reconfiguration (DR). The @@ -240,7 +239,6 @@ by newlines, where \fIname\fR is the name of the return data item that RCM expects and \fIvalue\fR is the value associated with the data item. .RE .SS "Environment" -.sp .LP The initial environment of RCM scripts is set as follows: .RS +4 @@ -365,7 +363,6 @@ commands, environment parameters, and name-value pairs is ASCII unless the controlling environment variables are specified otherwise. .SS "Commands" .SS "\fBscriptinfo\fR" -.sp .LP The \fBscriptinfo\fR command is invoked to gather information about the script. .sp @@ -416,7 +413,6 @@ pair \fBrcm_failure_reason\fR and exit with status 1. .RE .SS "\fBregister\fR" -.sp .LP The \fBregister\fR command is invoked to allow a script to specify the resources that it or its application handles that could potentially be removed @@ -450,7 +446,6 @@ pair \fBrcm_failure_reason\fR and exit with status 1. .RE .SS "\fBresourceinfo\fR \fIresourcename\fR" -.sp .LP The \fBresourceinfo\fR command is invoked to get the usage information about \fIresourcename\fR. @@ -478,7 +473,6 @@ pair \fBrcm_failure_reason\fR and exit with status 1. .RE .SS "\fBqueryremove\fR \fIresourcename\fR" -.sp .LP Prior to removing the resource from the system, the \fBqueryremove\fR command is invoked to query the script to determine whether the script can release the @@ -535,7 +529,6 @@ name-value pair \fBrcm_failure_reason\fR and exit with status 1. .RE .SS "\fBpreremove\fR \fIresourcename\fR" -.sp .LP The \fBpreremove\fR command is invoked prior to an attempt to remove the given \fIresourcename\fR. In response to this command the script can either release @@ -590,7 +583,6 @@ name-value pair \fBrcm_failure_reason\fR and exit with status 1. .RE .SS "\fBpostremove\fR \fIresourcename\fR" -.sp .LP The \fBpostremove\fR command is invoked after the given \fIresourcename\fR has been removed. @@ -628,7 +620,6 @@ pair \fBrcm_failure_reason\fR and exit with status 1. .RE .SS "Logging" -.sp .LP A script must log all error and debug messages by writing to stdout the name-value pairs listed below. The logged messages go to \fBsyslogd\fR(1M) with @@ -676,7 +667,6 @@ the amount of information to log. \fBRCM_ENV_DEBUG_LEVEL\fR is a numeric value ranging from 0 to 9, with 0 meaning log the least amount of information and 9 meaning log the most. .SS "Installing or Removing RCM Scripts" -.sp .LP You must use the following format to name a script: .sp @@ -739,7 +729,6 @@ Scripts for any hardware .RE .SS "Installing a Script" -.sp .LP To install a script, copy the script to the appropriate directory from the list above, change the userid and the groupid of the script to the desired values, @@ -755,7 +744,6 @@ and send \fBSIGHUP\fR to \fBrcm_daemon\fR. For example: .sp .SS "Removing a script" -.sp .LP Remove the script from the appropriate directory from the list above and send \fBSIGHUP\fR to \fBrcm_daemon\fR. For example: @@ -854,7 +842,7 @@ sub do_resourceinfo my ($rsrc, $unit); $rsrc = shift(@ARGV); - if ($rsrc =~ /^\/dev\/rmt\/([0-9]+)$/) { + if ($rsrc =~ /^\e/dev\e/rmt\e/([0-9]+)$/) { $unit = $1; print "rcm_resource_usage_info=Backup Tape Unit Number $unit\en"; exit (0); @@ -900,7 +888,6 @@ sub do_preremove .in -2 .SH EXIT STATUS -.sp .LP A script must exit with following exit status values: .sp @@ -948,7 +935,6 @@ name-value pair \fBrcm_failure_reason\fR before exiting. .RE .SH ERRORS -.sp .LP If a script cannot successfully process an RCM command, it must supply to the RCM a message indicating the reason for failure by writing a name-value pair, @@ -967,7 +953,6 @@ rcm_failure_reason=\fIfailure_reason\fR where \fIfailure_reason\fR is a localized human readable message describing the reason for failure of the RCM command. .SH ATTRIBUTES -.sp .LP See \fBattributes\fR(5) for descriptions of the following attributes: .sp @@ -983,13 +968,11 @@ Interface Stability Evolving .TE .SH SEE ALSO -.sp .LP \fBgettext\fR(1), \fBcfgadm\fR(1M), \fBcfgadm_scsi\fR(1M), \fBcfgadm_pci\fR(1M), \fBsyslog\fR(3C), \fBsignal.h\fR(3HEAD), \fBsyslog.conf\fR(4), \fBattributes\fR(5), \fBenviron\fR(5) .SH NOTES -.sp .LP RCM scripts are expected to properly handle all RCM commands that the script implements and to log all errors. Only root has permission to add or remove an diff --git a/usr/src/man/man5/eqn.5 b/usr/src/man/man5/eqn.5 index bfdb0cd58c..5fcf9ec3ea 100644 --- a/usr/src/man/man5/eqn.5 +++ b/usr/src/man/man5/eqn.5 @@ -1,4 +1,4 @@ -.\" $Id: eqn.7,v 1.34 2015/03/09 20:17:23 schwarze Exp $ +.\" $Id: eqn.7,v 1.35 2015/03/30 16:06:14 schwarze Exp $ .\" .\" Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2014 Ingo Schwarze <schwarze@openbsd.org> @@ -15,7 +15,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 9 2015 $ +.Dd $Mdocdate: March 30 2015 $ .Dt EQN 5 .Os .Sh NAME @@ -146,7 +146,7 @@ is used as the delimiter for the value .Ar val . This allows for arbitrary enclosure of terms (not just quotes), such as .Pp -.D1 Cm define Ar foo 'bar baz' +.D1 Cm define Ar foo \(aqbar baz\(aq .D1 Cm define Ar foo cbar bazc .Pp It is an error to have an empty @@ -166,8 +166,8 @@ created. Definitions can create arbitrary strings, for example, the following is a legal construction. .Bd -literal -offset indent -define foo 'define' -foo bar 'baz' +define foo \(aqdefine\(aq +foo bar \(aqbaz\(aq .Ed .Pp Self-referencing definitions will raise an error. diff --git a/usr/src/man/man5/mandoc_char.5 b/usr/src/man/man5/mandoc_char.5 index 48f8348c8e..cf102bb840 100644 --- a/usr/src/man/man5/mandoc_char.5 +++ b/usr/src/man/man5/mandoc_char.5 @@ -1,8 +1,8 @@ -.\" $Id: mandoc_char.7,v 1.59 2015/01/20 19:39:34 schwarze Exp $ +.\" $Id: mandoc_char.7,v 1.63 2015/09/02 15:38:35 schwarze Exp $ .\" .\" Copyright (c) 2003 Jason McIntyre <jmc@openbsd.org> .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> -.\" Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org> +.\" Copyright (c) 2011, 2013, 2015 Ingo Schwarze <schwarze@openbsd.org> .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -16,7 +16,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: January 20 2015 $ +.Dd $Mdocdate: September 2 2015 $ .Dt MANDOC_CHAR 5 .Os .Sh NAME @@ -49,7 +49,7 @@ names; instead, provide ASCII transcriptions of the names. .Ss Dashes and Hyphens In typography there are different types of dashes of various width: the hyphen (-), -the minus sign (\-), +the minus sign (\(mi), the en-dash (\(en), and the em-dash (\(em). .Pp @@ -64,10 +64,10 @@ lorry-driver .Pp The mathematical minus sign is used for negative numbers or subtraction. It should be written as -.Sq \e- : +.Sq \e(mi : .Bd -unfilled -offset indent -a = 3 \e- 1; -b = \e-2; +a = 3 \e(mi 1; +b = \e(mi2; .Ed .Pp The en-dash is used to separate the two elements of a range, @@ -142,6 +142,28 @@ Note that on text lines, literal double-quote characters can be used verbatim. All other quote-like characters can be used verbatim as well, even on request and macro lines. +.Ss Accents +In output modes supporting such special output characters, for example +.Fl T Cm pdf , +some +.Xr mandoc_roff 5 +formatters convert the following ASCII input characters to the +following Unicode special output characters: +.Bl -column x(ga U+2018 -offset indent +.It \(ga Ta U+2018 Ta left single quotation mark +.It \(aq Ta U+2019 Ta right single quotation mark +.It \(ti Ta U+02DC Ta small tilde +.El +.Pp +In prose, this automatic substitution is often desirable; +but when these characters have to be displayed as plain ASCII +characters, for example in source code samples, they require +escaping to render as follows: +.Bl -column x(ga U+2018 -offset indent +.It \e(ga Ta U+0060 Ta grave accent +.It \e(aq Ta U+0027 Ta apostrophe +.It \e(ti Ta U+007E Ta tilde +.El .Ss Periods The period .Pq Sq \&. @@ -196,7 +218,7 @@ Spacing: .Bl -column "Input" "Description" -offset indent -compact .It Em Input Ta Em Description .It Sq \e\ \& Ta unpaddable non-breaking space -.It \e~ Ta paddable non-breaking space +.It \e\(ti Ta paddable non-breaking space .It \e0 Ta unpaddable, breaking digit-width space .It \e| Ta one-sixth \e(em narrow space, zero width in nroff mode .It \e^ Ta one-twelfth \e(em half-narrow space, zero width in nroff @@ -371,9 +393,9 @@ Mathematical: .It \e(ne Ta \(ne Ta not equivalent .It \e(ap Ta \(ap Ta tilde operator .It \e(|= Ta \(|= Ta asymptotically equal -.It \e(=~ Ta \(=~ Ta approximately equal -.It \e(~~ Ta \(~~ Ta almost equal -.It \e(~= Ta \(~= Ta almost equal +.It \e(=\(ti Ta \(=~ Ta approximately equal +.It \e(\(ti\(ti Ta \(~~ Ta almost equal +.It \e(\(ti= Ta \(~= Ta almost equal .It \e(pt Ta \(pt Ta proportionate .It \e(es Ta \(es Ta empty set .It \e(mo Ta \(mo Ta element @@ -436,15 +458,15 @@ Accents: .It \e(a. Ta \(a. Ta dotted .It \e(a^ Ta \(a^ Ta circumflex .It \e(aa Ta \(aa Ta acute -.It \e' Ta \' Ta acute +.It \e\(aq Ta \' Ta acute .It \e(ga Ta \(ga Ta grave -.It \e` Ta \` Ta grave +.It \e\(ga Ta \` Ta grave .It \e(ab Ta \(ab Ta breve .It \e(ac Ta \(ac Ta cedilla .It \e(ad Ta \(ad Ta dieresis .It \e(ah Ta \(ah Ta caron .It \e(ao Ta \(ao Ta ring -.It \e(a~ Ta \(a~ Ta tilde +.It \e(a\(ti Ta \(a~ Ta tilde .It \e(ho Ta \(ho Ta ogonek .It \e(ha Ta \(ha Ta hat (text) .It \e(ti Ta \(ti Ta tilde (text) @@ -453,32 +475,32 @@ Accents: Accented letters: .Bl -column "Input" "Rendered" "Description" -offset indent -compact .It Em Input Ta Em Rendered Ta Em Description -.It \e('A Ta \('A Ta acute A -.It \e('E Ta \('E Ta acute E -.It \e('I Ta \('I Ta acute I -.It \e('O Ta \('O Ta acute O -.It \e('U Ta \('U Ta acute U -.It \e('a Ta \('a Ta acute a -.It \e('e Ta \('e Ta acute e -.It \e('i Ta \('i Ta acute i -.It \e('o Ta \('o Ta acute o -.It \e('u Ta \('u Ta acute u -.It \e(`A Ta \(`A Ta grave A -.It \e(`E Ta \(`E Ta grave E -.It \e(`I Ta \(`I Ta grave I -.It \e(`O Ta \(`O Ta grave O -.It \e(`U Ta \(`U Ta grave U -.It \e(`a Ta \(`a Ta grave a -.It \e(`e Ta \(`e Ta grave e -.It \e(`i Ta \(`i Ta grave i -.It \e(`o Ta \(`i Ta grave o -.It \e(`u Ta \(`u Ta grave u -.It \e(~A Ta \(~A Ta tilde A -.It \e(~N Ta \(~N Ta tilde N -.It \e(~O Ta \(~O Ta tilde O -.It \e(~a Ta \(~a Ta tilde a -.It \e(~n Ta \(~n Ta tilde n -.It \e(~o Ta \(~o Ta tilde o +.It \e(\(aqA Ta \('A Ta acute A +.It \e(\(aqE Ta \('E Ta acute E +.It \e(\(aqI Ta \('I Ta acute I +.It \e(\(aqO Ta \('O Ta acute O +.It \e(\(aqU Ta \('U Ta acute U +.It \e(\(aqa Ta \('a Ta acute a +.It \e(\(aqe Ta \('e Ta acute e +.It \e(\(aqi Ta \('i Ta acute i +.It \e(\(aqo Ta \('o Ta acute o +.It \e(\(aqu Ta \('u Ta acute u +.It \e(\(gaA Ta \(`A Ta grave A +.It \e(\(gaE Ta \(`E Ta grave E +.It \e(\(gaI Ta \(`I Ta grave I +.It \e(\(gaO Ta \(`O Ta grave O +.It \e(\(gaU Ta \(`U Ta grave U +.It \e(\(gaa Ta \(`a Ta grave a +.It \e(\(gae Ta \(`e Ta grave e +.It \e(\(gai Ta \(`i Ta grave i +.It \e(\(gao Ta \(`i Ta grave o +.It \e(\(gau Ta \(`u Ta grave u +.It \e(\(tiA Ta \(~A Ta tilde A +.It \e(\(tiN Ta \(~N Ta tilde N +.It \e(\(tiO Ta \(~O Ta tilde O +.It \e(\(tia Ta \(~a Ta tilde a +.It \e(\(tin Ta \(~n Ta tilde n +.It \e(\(tio Ta \(~o Ta tilde o .It \e(:A Ta \(:A Ta dieresis A .It \e(:E Ta \(:E Ta dieresis E .It \e(:I Ta \(:I Ta dieresis I @@ -657,7 +679,7 @@ manual. .Sh UNICODE CHARACTERS The escape sequences .Pp -.Dl \e[uXXXX] and \eC'uXXXX' +.Dl \e[uXXXX] and \eC\(aquXXXX\(aq .Pp are interpreted as Unicode codepoints. The codepoint must be in the range above U+0080 and less than U+10FFFF. @@ -669,10 +691,6 @@ must be given as uppercase characters, and points must be zero-padded to four characters; if greater than four characters, no zero padding is allowed. Unicode surrogates are not allowed. -.\" .Pp -.\" Unicode glyphs attenuate to the -.\" .Sq \&? -.\" character if invalid or not rendered by current output media. .Sh NUMBERED CHARACTERS For backward compatibility with existing manuals, .Xr mandoc 1 @@ -685,7 +703,7 @@ escape sequence, inserting the character from the current character set into the output. Of course, this is inherently non-portable and is already marked as deprecated in the Heirloom roff manual. -For example, do not use \eN'34', use \e(dq, or even the plain +For example, do not use \eN\(aq34\(aq, use \e(dq, or even the plain .Sq \(dq character where possible. .Sh COMPATIBILITY @@ -702,14 +720,14 @@ In .Fl T Ns Cm ascii , the \e(ss, \e(nm, \e(nb, \e(nc, \e(ib, \e(ip, \e(pp, \e[sum], \e[product], -\e[coproduct], \e(gr, \e(\-h, and \e(a. special characters render +\e[coproduct], \e(gr, \e(-h, and \e(a. special characters render differently between mandoc and groff. .It In .Fl T Ns Cm html and .Fl T Ns Cm xhtml , -the \e(~=, \e(nb, and \e(nc special characters render differently +the \e(\(ti=, \e(nb, and \e(nc special characters render differently between mandoc and groff. .It The diff --git a/usr/src/man/man5/mandoc_roff.5 b/usr/src/man/man5/mandoc_roff.5 index 55be0155aa..471c82e5ce 100644 --- a/usr/src/man/man5/mandoc_roff.5 +++ b/usr/src/man/man5/mandoc_roff.5 @@ -1,7 +1,7 @@ -.\" $Id: roff.7,v 1.70 2015/02/17 17:16:52 schwarze Exp $ +.\" $Id: roff.7,v 1.75 2015/09/24 18:41:22 schwarze Exp $ .\" .\" Copyright (c) 2010, 2011, 2012 Kristaps Dzonsons <kristaps@bsd.lv> -.\" Copyright (c) 2010, 2011, 2013, 2014 Ingo Schwarze <schwarze@openbsd.org> +.\" Copyright (c) 2010, 2011, 2013-2015 Ingo Schwarze <schwarze@openbsd.org> .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -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: April 9 2016 $ +.Dd $Mdocdate: September 24 2015 $ .Dt MANDOC_ROFF 5 .Os .Sh NAME @@ -665,6 +665,8 @@ produces .D1 \efI\e^XtFree\e^\efP. .Pp in the input stream, and thus in the output: \fI\^XtFree\^\fP. +Each occurrence of \e\e$* is replaced with all the arguments, +joined together with single blank characters. .Pp Since macros and user-defined strings share a common string table, defining a macro @@ -1057,8 +1059,6 @@ If the first character of COND is .Pq string defined , .Sq e .Pq even page , -.Sq r -.Pq register accessed , .Sq t .Pq troff mode , or @@ -1066,6 +1066,11 @@ or .Pq vroff mode , COND evaluates to false. .It +If the first character of COND is +.Sq r , +it evaluates to true if the rest of COND is the name of an existing +number register; otherwise, it evaluates to false. +.It If COND starts with a parenthesis or with an optionally signed integer number, it is evaluated according to the rules of .Sx Numerical expressions @@ -1337,7 +1342,7 @@ Currently unsupported. Temporarily turn off line numbering. Currently unsupported. .Ss \&nop -Exexute the rest of the input line as a request or macro line. +Execute the rest of the input line as a request or macro line. Currently unsupported. .Ss \&nr Define or change a register. @@ -1679,7 +1684,7 @@ Notify on change of string or macro. This is a Heirloom extension and currently ignored. .Ss \&watchlength On change, report the contents of macros and strings -up to the sepcified length. +up to the specified length. This is a Heirloom extension and currently ignored. .Ss \&watchn Notify on change of register. @@ -1774,7 +1779,7 @@ minimum (not available in C) maximum (not available in C) .El .Pp -There is no concept of precendence; evaluation proceeds from left to right, +There is no concept of precedence; evaluation proceeds from left to right, except when subexpressions are enclosed in parantheses. Inside parentheses, whitespace is ignored. .Sh ESCAPE SEQUENCE REFERENCE @@ -1834,9 +1839,15 @@ For short names, there are variants .No \e* Ns Ar c and .No \e*( Ns Ar cc . +.Ss \e, +Left italic correction (groff extension); ignored by +.Xr mandoc 1 . .Ss \e- Special character .Dq mathematical minus sign . +.Ss \e/ +Right italic correction (groff extension); ignored by +.Xr mandoc 1 . .Ss \e[ Ns Ar name ] .Sx Special Characters with names of arbitrary length, see @@ -2028,10 +2039,7 @@ Print with zero width and height; ignored by .Xr mandoc 1 . .Ss \ez -Output the next character without advancing the cursor position; -approximated in -.Xr mandoc 1 -by simply skipping the next character. +Output the next character without advancing the cursor position. .Sh COMPATIBILITY The .Xr mandoc 1 @@ -2088,7 +2096,7 @@ loops are not. .Pp The special semantics of the .Cm nS -number register is an idiosyncrasy of +number register is an idiosyncracy of .Ox manuals and not supported by other .Xr mdoc 5 diff --git a/usr/src/man/man5/mdoc.5 b/usr/src/man/man5/mdoc.5 index 5be6dfb4a8..643a269781 100644 --- a/usr/src/man/man5/mdoc.5 +++ b/usr/src/man/man5/mdoc.5 @@ -1,4 +1,4 @@ -.\" $Id: mdoc.7,v 1.252 2015/02/23 13:31:04 schwarze Exp $ +.\" $Id: mdoc.7,v 1.257 2015/11/05 12:06:45 schwarze Exp $ .\" .\" Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv> .\" Copyright (c) 2010, 2011, 2013 Ingo Schwarze <schwarze@openbsd.org> @@ -16,10 +16,10 @@ .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .\" -.\" Copyright 2014 Garrett D'Amore <garrett@dmaore.org> +.\" Copyright 2014 Garrett D'Amore <garrett@damore.org> .\" Copyright 2015 Nexenta Systems, Inc. All rights reserved. .\" -.Dd Mar 13, 2016 +.Dd $Mdocdate: November 5 2015 $ .Dt MDOC 5 .Os .Sh NAME @@ -309,6 +309,11 @@ Print verbose information. \&.El .Ed .Pp +List the options in alphabetical order, +uppercase before lowercase for each letter and +with no regard to whether an option takes an argument. +Put digits in ascending order before all letter options. +.Pp Manuals not documenting a command won't include the above fragment. .Pp Since the @@ -1699,7 +1704,7 @@ See also A function name. Its syntax is as follows: .Bd -ragged -offset indent -.Pf \. Ns Sx \&Fn +.Pf . Sx \&Fn .Op Ar functype .Ar funcname .Op Oo Ar argtype Oc Ar argname @@ -2170,7 +2175,7 @@ It is suggested to leave it unspecified, in which case .Xr mandoc 1 uses its .Fl Ios -argument, or, if that isn't specified either, +argument or, if that isn't specified either, .Fa sysname and .Fa release @@ -2232,19 +2237,23 @@ See also Close parenthesised context opened by .Sx \&Po . .Ss \&Pf -Removes the space between its argument -.Pq Dq prefix -and the following macro. +Removes the space between its argument and the following macro. Its syntax is as follows: .Pp .D1 .Pf Ar prefix macro arguments ... .Pp This is equivalent to: .Pp -.D1 .No Ar prefix No \&Ns Ar macro arguments ... +.D1 .No \e& Ns Ar prefix No \&Ns Ar macro arguments ... +.Pp +The +.Ar prefix +argument is not parsed for macro names or delimiters, +but used verbatim as if it were escaped. .Pp Examples: .Dl ".Pf $ Ar variable_name" +.Dl ".Pf . Ar macro_name" .Dl ".Pf 0x Ar hex_digits" .Pp See also @@ -2344,7 +2353,7 @@ Examples: \&.%A J. D. Ullman \&.%B Introduction to Automata Theory, Languages, and Computation \&.%I Addison-Wesley -\&.%C Reading, Massachusettes +\&.%C Reading, Massachusetts \&.%D 1979 \&.Re .Ed |