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