xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/lib/Pod/Man.pm (revision 0:68f95e015346)
1*0Sstevel@tonic-gate# Pod::Man -- Convert POD data to formatted *roff input.
2*0Sstevel@tonic-gate# $Id: Man.pm,v 1.37 2003/03/30 22:34:11 eagle Exp $
3*0Sstevel@tonic-gate#
4*0Sstevel@tonic-gate# Copyright 1999, 2000, 2001, 2002, 2003 by Russ Allbery <rra@stanford.edu>
5*0Sstevel@tonic-gate#
6*0Sstevel@tonic-gate# This program is free software; you may redistribute it and/or modify it
7*0Sstevel@tonic-gate# under the same terms as Perl itself.
8*0Sstevel@tonic-gate#
9*0Sstevel@tonic-gate# This module translates POD documentation into *roff markup using the man
10*0Sstevel@tonic-gate# macro set, and is intended for converting POD documents written as Unix
11*0Sstevel@tonic-gate# manual pages to manual pages that can be read by the man(1) command.  It is
12*0Sstevel@tonic-gate# a replacement for the pod2man command distributed with versions of Perl
13*0Sstevel@tonic-gate# prior to 5.6.
14*0Sstevel@tonic-gate#
15*0Sstevel@tonic-gate# Perl core hackers, please note that this module is also separately
16*0Sstevel@tonic-gate# maintained outside of the Perl core as part of the podlators.  Please send
17*0Sstevel@tonic-gate# me any patches at the address above in addition to sending them to the
18*0Sstevel@tonic-gate# standard Perl mailing lists.
19*0Sstevel@tonic-gate
20*0Sstevel@tonic-gate##############################################################################
21*0Sstevel@tonic-gate# Modules and declarations
22*0Sstevel@tonic-gate##############################################################################
23*0Sstevel@tonic-gate
24*0Sstevel@tonic-gatepackage Pod::Man;
25*0Sstevel@tonic-gate
26*0Sstevel@tonic-gaterequire 5.005;
27*0Sstevel@tonic-gate
28*0Sstevel@tonic-gateuse Carp qw(carp croak);
29*0Sstevel@tonic-gateuse Pod::ParseLink qw(parselink);
30*0Sstevel@tonic-gateuse Pod::Parser ();
31*0Sstevel@tonic-gate
32*0Sstevel@tonic-gateuse strict;
33*0Sstevel@tonic-gateuse subs qw(makespace);
34*0Sstevel@tonic-gateuse vars qw(@ISA %ESCAPES $PREAMBLE $VERSION);
35*0Sstevel@tonic-gate
36*0Sstevel@tonic-gate@ISA = qw(Pod::Parser);
37*0Sstevel@tonic-gate
38*0Sstevel@tonic-gate# Don't use the CVS revision as the version, since this module is also in Perl
39*0Sstevel@tonic-gate# core and too many things could munge CVS magic revision strings.  This
40*0Sstevel@tonic-gate# number should ideally be the same as the CVS revision in podlators, however.
41*0Sstevel@tonic-gate$VERSION = 1.37;
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gate
44*0Sstevel@tonic-gate##############################################################################
45*0Sstevel@tonic-gate# Preamble and *roff output tables
46*0Sstevel@tonic-gate##############################################################################
47*0Sstevel@tonic-gate
48*0Sstevel@tonic-gate# The following is the static preamble which starts all *roff output we
49*0Sstevel@tonic-gate# generate.  It's completely static except for the font to use as a
50*0Sstevel@tonic-gate# fixed-width font, which is designed by @CFONT@, and the left and right
51*0Sstevel@tonic-gate# quotes to use for C<> text, designated by @LQOUTE@ and @RQUOTE@.  $PREAMBLE
52*0Sstevel@tonic-gate# should therefore be run through s/\@CFONT\@/<font>/g before output.
53*0Sstevel@tonic-gate$PREAMBLE = <<'----END OF PREAMBLE----';
54*0Sstevel@tonic-gate.de Sh \" Subsection heading
55*0Sstevel@tonic-gate.br
56*0Sstevel@tonic-gate.if t .Sp
57*0Sstevel@tonic-gate.ne 5
58*0Sstevel@tonic-gate.PP
59*0Sstevel@tonic-gate\fB\\$1\fR
60*0Sstevel@tonic-gate.PP
61*0Sstevel@tonic-gate..
62*0Sstevel@tonic-gate.de Sp \" Vertical space (when we can't use .PP)
63*0Sstevel@tonic-gate.if t .sp .5v
64*0Sstevel@tonic-gate.if n .sp
65*0Sstevel@tonic-gate..
66*0Sstevel@tonic-gate.de Vb \" Begin verbatim text
67*0Sstevel@tonic-gate.ft @CFONT@
68*0Sstevel@tonic-gate.nf
69*0Sstevel@tonic-gate.ne \\$1
70*0Sstevel@tonic-gate..
71*0Sstevel@tonic-gate.de Ve \" End verbatim text
72*0Sstevel@tonic-gate.ft R
73*0Sstevel@tonic-gate.fi
74*0Sstevel@tonic-gate..
75*0Sstevel@tonic-gate.\" Set up some character translations and predefined strings.  \*(-- will
76*0Sstevel@tonic-gate.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
77*0Sstevel@tonic-gate.\" double quote, and \*(R" will give a right double quote.  | will give a
78*0Sstevel@tonic-gate.\" real vertical bar.  \*(C+ will give a nicer C++.  Capital omega is used to
79*0Sstevel@tonic-gate.\" do unbreakable dashes and therefore won't be available.  \*(C` and \*(C'
80*0Sstevel@tonic-gate.\" expand to `' in nroff, nothing in troff, for use with C<>.
81*0Sstevel@tonic-gate.tr \(*W-|\(bv\*(Tr
82*0Sstevel@tonic-gate.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
83*0Sstevel@tonic-gate.ie n \{\
84*0Sstevel@tonic-gate.    ds -- \(*W-
85*0Sstevel@tonic-gate.    ds PI pi
86*0Sstevel@tonic-gate.    if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
87*0Sstevel@tonic-gate.    if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\"  diablo 12 pitch
88*0Sstevel@tonic-gate.    ds L" ""
89*0Sstevel@tonic-gate.    ds R" ""
90*0Sstevel@tonic-gate.    ds C` @LQUOTE@
91*0Sstevel@tonic-gate.    ds C' @RQUOTE@
92*0Sstevel@tonic-gate'br\}
93*0Sstevel@tonic-gate.el\{\
94*0Sstevel@tonic-gate.    ds -- \|\(em\|
95*0Sstevel@tonic-gate.    ds PI \(*p
96*0Sstevel@tonic-gate.    ds L" ``
97*0Sstevel@tonic-gate.    ds R" ''
98*0Sstevel@tonic-gate'br\}
99*0Sstevel@tonic-gate.\"
100*0Sstevel@tonic-gate.\" If the F register is turned on, we'll generate index entries on stderr for
101*0Sstevel@tonic-gate.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
102*0Sstevel@tonic-gate.\" entries marked with X<> in POD.  Of course, you'll have to process the
103*0Sstevel@tonic-gate.\" output yourself in some meaningful fashion.
104*0Sstevel@tonic-gate.if \nF \{\
105*0Sstevel@tonic-gate.    de IX
106*0Sstevel@tonic-gate.    tm Index:\\$1\t\\n%\t"\\$2"
107*0Sstevel@tonic-gate..
108*0Sstevel@tonic-gate.    nr % 0
109*0Sstevel@tonic-gate.    rr F
110*0Sstevel@tonic-gate.\}
111*0Sstevel@tonic-gate.\"
112*0Sstevel@tonic-gate.\" For nroff, turn off justification.  Always turn off hyphenation; it makes
113*0Sstevel@tonic-gate.\" way too many mistakes in technical documents.
114*0Sstevel@tonic-gate.hy 0
115*0Sstevel@tonic-gate.if n .na
116*0Sstevel@tonic-gate.\"
117*0Sstevel@tonic-gate.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
118*0Sstevel@tonic-gate.\" Fear.  Run.  Save yourself.  No user-serviceable parts.
119*0Sstevel@tonic-gate.    \" fudge factors for nroff and troff
120*0Sstevel@tonic-gate.if n \{\
121*0Sstevel@tonic-gate.    ds #H 0
122*0Sstevel@tonic-gate.    ds #V .8m
123*0Sstevel@tonic-gate.    ds #F .3m
124*0Sstevel@tonic-gate.    ds #[ \f1
125*0Sstevel@tonic-gate.    ds #] \fP
126*0Sstevel@tonic-gate.\}
127*0Sstevel@tonic-gate.if t \{\
128*0Sstevel@tonic-gate.    ds #H ((1u-(\\\\n(.fu%2u))*.13m)
129*0Sstevel@tonic-gate.    ds #V .6m
130*0Sstevel@tonic-gate.    ds #F 0
131*0Sstevel@tonic-gate.    ds #[ \&
132*0Sstevel@tonic-gate.    ds #] \&
133*0Sstevel@tonic-gate.\}
134*0Sstevel@tonic-gate.    \" simple accents for nroff and troff
135*0Sstevel@tonic-gate.if n \{\
136*0Sstevel@tonic-gate.    ds ' \&
137*0Sstevel@tonic-gate.    ds ` \&
138*0Sstevel@tonic-gate.    ds ^ \&
139*0Sstevel@tonic-gate.    ds , \&
140*0Sstevel@tonic-gate.    ds ~ ~
141*0Sstevel@tonic-gate.    ds /
142*0Sstevel@tonic-gate.\}
143*0Sstevel@tonic-gate.if t \{\
144*0Sstevel@tonic-gate.    ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
145*0Sstevel@tonic-gate.    ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
146*0Sstevel@tonic-gate.    ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
147*0Sstevel@tonic-gate.    ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
148*0Sstevel@tonic-gate.    ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
149*0Sstevel@tonic-gate.    ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
150*0Sstevel@tonic-gate.\}
151*0Sstevel@tonic-gate.    \" troff and (daisy-wheel) nroff accents
152*0Sstevel@tonic-gate.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
153*0Sstevel@tonic-gate.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
154*0Sstevel@tonic-gate.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
155*0Sstevel@tonic-gate.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
156*0Sstevel@tonic-gate.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
157*0Sstevel@tonic-gate.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
158*0Sstevel@tonic-gate.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
159*0Sstevel@tonic-gate.ds ae a\h'-(\w'a'u*4/10)'e
160*0Sstevel@tonic-gate.ds Ae A\h'-(\w'A'u*4/10)'E
161*0Sstevel@tonic-gate.    \" corrections for vroff
162*0Sstevel@tonic-gate.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
163*0Sstevel@tonic-gate.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
164*0Sstevel@tonic-gate.    \" for low resolution devices (crt and lpr)
165*0Sstevel@tonic-gate.if \n(.H>23 .if \n(.V>19 \
166*0Sstevel@tonic-gate\{\
167*0Sstevel@tonic-gate.    ds : e
168*0Sstevel@tonic-gate.    ds 8 ss
169*0Sstevel@tonic-gate.    ds o a
170*0Sstevel@tonic-gate.    ds d- d\h'-1'\(ga
171*0Sstevel@tonic-gate.    ds D- D\h'-1'\(hy
172*0Sstevel@tonic-gate.    ds th \o'bp'
173*0Sstevel@tonic-gate.    ds Th \o'LP'
174*0Sstevel@tonic-gate.    ds ae ae
175*0Sstevel@tonic-gate.    ds Ae AE
176*0Sstevel@tonic-gate.\}
177*0Sstevel@tonic-gate.rm #[ #] #H #V #F C
178*0Sstevel@tonic-gate----END OF PREAMBLE----
179*0Sstevel@tonic-gate#`# for cperl-mode
180*0Sstevel@tonic-gate
181*0Sstevel@tonic-gate# This table is taken nearly verbatim from Tom Christiansen's pod2man.  It
182*0Sstevel@tonic-gate# assumes that the standard preamble has already been printed, since that's
183*0Sstevel@tonic-gate# what defines all of the accent marks.  Note that some of these are quoted
184*0Sstevel@tonic-gate# with double quotes since they contain embedded single quotes, so use \\
185*0Sstevel@tonic-gate# uniformly for backslash for readability.
186*0Sstevel@tonic-gate%ESCAPES = (
187*0Sstevel@tonic-gate    'amp'       =>    '&',      # ampersand
188*0Sstevel@tonic-gate    'apos'      =>    "'",      # apostrophe
189*0Sstevel@tonic-gate    'lt'        =>    '<',      # left chevron, less-than
190*0Sstevel@tonic-gate    'gt'        =>    '>',      # right chevron, greater-than
191*0Sstevel@tonic-gate    'quot'      =>    '"',      # double quote
192*0Sstevel@tonic-gate    'sol'       =>    '/',      # solidus (forward slash)
193*0Sstevel@tonic-gate    'verbar'    =>    '|',      # vertical bar
194*0Sstevel@tonic-gate
195*0Sstevel@tonic-gate    'Aacute'    =>    "A\\*'",  # capital A, acute accent
196*0Sstevel@tonic-gate    'aacute'    =>    "a\\*'",  # small a, acute accent
197*0Sstevel@tonic-gate    'Acirc'     =>    'A\\*^',  # capital A, circumflex accent
198*0Sstevel@tonic-gate    'acirc'     =>    'a\\*^',  # small a, circumflex accent
199*0Sstevel@tonic-gate    'AElig'     =>    '\*(AE',  # capital AE diphthong (ligature)
200*0Sstevel@tonic-gate    'aelig'     =>    '\*(ae',  # small ae diphthong (ligature)
201*0Sstevel@tonic-gate    'Agrave'    =>    "A\\*`",  # capital A, grave accent
202*0Sstevel@tonic-gate    'agrave'    =>    "A\\*`",  # small a, grave accent
203*0Sstevel@tonic-gate    'Aring'     =>    'A\\*o',  # capital A, ring
204*0Sstevel@tonic-gate    'aring'     =>    'a\\*o',  # small a, ring
205*0Sstevel@tonic-gate    'Atilde'    =>    'A\\*~',  # capital A, tilde
206*0Sstevel@tonic-gate    'atilde'    =>    'a\\*~',  # small a, tilde
207*0Sstevel@tonic-gate    'Auml'      =>    'A\\*:',  # capital A, dieresis or umlaut mark
208*0Sstevel@tonic-gate    'auml'      =>    'a\\*:',  # small a, dieresis or umlaut mark
209*0Sstevel@tonic-gate    'Ccedil'    =>    'C\\*,',  # capital C, cedilla
210*0Sstevel@tonic-gate    'ccedil'    =>    'c\\*,',  # small c, cedilla
211*0Sstevel@tonic-gate    'Eacute'    =>    "E\\*'",  # capital E, acute accent
212*0Sstevel@tonic-gate    'eacute'    =>    "e\\*'",  # small e, acute accent
213*0Sstevel@tonic-gate    'Ecirc'     =>    'E\\*^',  # capital E, circumflex accent
214*0Sstevel@tonic-gate    'ecirc'     =>    'e\\*^',  # small e, circumflex accent
215*0Sstevel@tonic-gate    'Egrave'    =>    'E\\*`',  # capital E, grave accent
216*0Sstevel@tonic-gate    'egrave'    =>    'e\\*`',  # small e, grave accent
217*0Sstevel@tonic-gate    'ETH'       =>    '\\*(D-', # capital Eth, Icelandic
218*0Sstevel@tonic-gate    'eth'       =>    '\\*(d-', # small eth, Icelandic
219*0Sstevel@tonic-gate    'Euml'      =>    'E\\*:',  # capital E, dieresis or umlaut mark
220*0Sstevel@tonic-gate    'euml'      =>    'e\\*:',  # small e, dieresis or umlaut mark
221*0Sstevel@tonic-gate    'Iacute'    =>    "I\\*'",  # capital I, acute accent
222*0Sstevel@tonic-gate    'iacute'    =>    "i\\*'",  # small i, acute accent
223*0Sstevel@tonic-gate    'Icirc'     =>    'I\\*^',  # capital I, circumflex accent
224*0Sstevel@tonic-gate    'icirc'     =>    'i\\*^',  # small i, circumflex accent
225*0Sstevel@tonic-gate    'Igrave'    =>    'I\\*`',  # capital I, grave accent
226*0Sstevel@tonic-gate    'igrave'    =>    'i\\*`',  # small i, grave accent
227*0Sstevel@tonic-gate    'Iuml'      =>    'I\\*:',  # capital I, dieresis or umlaut mark
228*0Sstevel@tonic-gate    'iuml'      =>    'i\\*:',  # small i, dieresis or umlaut mark
229*0Sstevel@tonic-gate    'Ntilde'    =>    'N\*~',   # capital N, tilde
230*0Sstevel@tonic-gate    'ntilde'    =>    'n\*~',   # small n, tilde
231*0Sstevel@tonic-gate    'Oacute'    =>    "O\\*'",  # capital O, acute accent
232*0Sstevel@tonic-gate    'oacute'    =>    "o\\*'",  # small o, acute accent
233*0Sstevel@tonic-gate    'Ocirc'     =>    'O\\*^',  # capital O, circumflex accent
234*0Sstevel@tonic-gate    'ocirc'     =>    'o\\*^',  # small o, circumflex accent
235*0Sstevel@tonic-gate    'Ograve'    =>    'O\\*`',  # capital O, grave accent
236*0Sstevel@tonic-gate    'ograve'    =>    'o\\*`',  # small o, grave accent
237*0Sstevel@tonic-gate    'Oslash'    =>    'O\\*/',  # capital O, slash
238*0Sstevel@tonic-gate    'oslash'    =>    'o\\*/',  # small o, slash
239*0Sstevel@tonic-gate    'Otilde'    =>    'O\\*~',  # capital O, tilde
240*0Sstevel@tonic-gate    'otilde'    =>    'o\\*~',  # small o, tilde
241*0Sstevel@tonic-gate    'Ouml'      =>    'O\\*:',  # capital O, dieresis or umlaut mark
242*0Sstevel@tonic-gate    'ouml'      =>    'o\\*:',  # small o, dieresis or umlaut mark
243*0Sstevel@tonic-gate    'szlig'     =>    '\*8',    # small sharp s, German (sz ligature)
244*0Sstevel@tonic-gate    'THORN'     =>    '\\*(Th', # capital THORN, Icelandic
245*0Sstevel@tonic-gate    'thorn'     =>    '\\*(th', # small thorn, Icelandic
246*0Sstevel@tonic-gate    'Uacute'    =>    "U\\*'",  # capital U, acute accent
247*0Sstevel@tonic-gate    'uacute'    =>    "u\\*'",  # small u, acute accent
248*0Sstevel@tonic-gate    'Ucirc'     =>    'U\\*^',  # capital U, circumflex accent
249*0Sstevel@tonic-gate    'ucirc'     =>    'u\\*^',  # small u, circumflex accent
250*0Sstevel@tonic-gate    'Ugrave'    =>    'U\\*`',  # capital U, grave accent
251*0Sstevel@tonic-gate    'ugrave'    =>    'u\\*`',  # small u, grave accent
252*0Sstevel@tonic-gate    'Uuml'      =>    'U\\*:',  # capital U, dieresis or umlaut mark
253*0Sstevel@tonic-gate    'uuml'      =>    'u\\*:',  # small u, dieresis or umlaut mark
254*0Sstevel@tonic-gate    'Yacute'    =>    "Y\\*'",  # capital Y, acute accent
255*0Sstevel@tonic-gate    'yacute'    =>    "y\\*'",  # small y, acute accent
256*0Sstevel@tonic-gate    'yuml'      =>    'y\\*:',  # small y, dieresis or umlaut mark
257*0Sstevel@tonic-gate
258*0Sstevel@tonic-gate    'nbsp'      =>    '\\ ',    # non-breaking space
259*0Sstevel@tonic-gate    'shy'       =>    '',       # soft (discretionary) hyphen
260*0Sstevel@tonic-gate);
261*0Sstevel@tonic-gate
262*0Sstevel@tonic-gate
263*0Sstevel@tonic-gate##############################################################################
264*0Sstevel@tonic-gate# Static helper functions
265*0Sstevel@tonic-gate##############################################################################
266*0Sstevel@tonic-gate
267*0Sstevel@tonic-gate# Protect leading quotes and periods against interpretation as commands.  Also
268*0Sstevel@tonic-gate# protect anything starting with a backslash, since it could expand or hide
269*0Sstevel@tonic-gate# something that *roff would interpret as a command.  This is overkill, but
270*0Sstevel@tonic-gate# it's much simpler than trying to parse *roff here.
271*0Sstevel@tonic-gatesub protect {
272*0Sstevel@tonic-gate    local $_ = shift;
273*0Sstevel@tonic-gate    s/^([.\'\\])/\\&$1/mg;
274*0Sstevel@tonic-gate    $_;
275*0Sstevel@tonic-gate}
276*0Sstevel@tonic-gate
277*0Sstevel@tonic-gate# Translate a font string into an escape.
278*0Sstevel@tonic-gatesub toescape { (length ($_[0]) > 1 ? '\f(' : '\f') . $_[0] }
279*0Sstevel@tonic-gate
280*0Sstevel@tonic-gate
281*0Sstevel@tonic-gate##############################################################################
282*0Sstevel@tonic-gate# Initialization
283*0Sstevel@tonic-gate##############################################################################
284*0Sstevel@tonic-gate
285*0Sstevel@tonic-gate# Initialize the object.  Here, we also process any additional options passed
286*0Sstevel@tonic-gate# to the constructor or set up defaults if none were given.  center is the
287*0Sstevel@tonic-gate# centered title, release is the version number, and date is the date for the
288*0Sstevel@tonic-gate# documentation.  Note that we can't know what file name we're processing due
289*0Sstevel@tonic-gate# to the architecture of Pod::Parser, so that *has* to either be passed to the
290*0Sstevel@tonic-gate# constructor or set separately with Pod::Man::name().
291*0Sstevel@tonic-gatesub initialize {
292*0Sstevel@tonic-gate    my $self = shift;
293*0Sstevel@tonic-gate
294*0Sstevel@tonic-gate    # Figure out the fixed-width font.  If user-supplied, make sure that they
295*0Sstevel@tonic-gate    # are the right length.
296*0Sstevel@tonic-gate    for (qw/fixed fixedbold fixeditalic fixedbolditalic/) {
297*0Sstevel@tonic-gate        if (defined $$self{$_}) {
298*0Sstevel@tonic-gate            if (length ($$self{$_}) < 1 || length ($$self{$_}) > 2) {
299*0Sstevel@tonic-gate                croak qq(roff font should be 1 or 2 chars,)
300*0Sstevel@tonic-gate                    . qq( not "$$self{$_}");
301*0Sstevel@tonic-gate            }
302*0Sstevel@tonic-gate        } else {
303*0Sstevel@tonic-gate            $$self{$_} = '';
304*0Sstevel@tonic-gate        }
305*0Sstevel@tonic-gate    }
306*0Sstevel@tonic-gate
307*0Sstevel@tonic-gate    # Set the default fonts.  We can't be sure what fixed bold-italic is going
308*0Sstevel@tonic-gate    # to be called, so default to just bold.
309*0Sstevel@tonic-gate    $$self{fixed}           ||= 'CW';
310*0Sstevel@tonic-gate    $$self{fixedbold}       ||= 'CB';
311*0Sstevel@tonic-gate    $$self{fixeditalic}     ||= 'CI';
312*0Sstevel@tonic-gate    $$self{fixedbolditalic} ||= 'CB';
313*0Sstevel@tonic-gate
314*0Sstevel@tonic-gate    # Set up a table of font escapes.  First number is fixed-width, second is
315*0Sstevel@tonic-gate    # bold, third is italic.
316*0Sstevel@tonic-gate    $$self{FONTS} = { '000' => '\fR', '001' => '\fI',
317*0Sstevel@tonic-gate                      '010' => '\fB', '011' => '\f(BI',
318*0Sstevel@tonic-gate                      '100' => toescape ($$self{fixed}),
319*0Sstevel@tonic-gate                      '101' => toescape ($$self{fixeditalic}),
320*0Sstevel@tonic-gate                      '110' => toescape ($$self{fixedbold}),
321*0Sstevel@tonic-gate                      '111' => toescape ($$self{fixedbolditalic})};
322*0Sstevel@tonic-gate
323*0Sstevel@tonic-gate    # Extra stuff for page titles.
324*0Sstevel@tonic-gate    $$self{center} = 'User Contributed Perl Documentation'
325*0Sstevel@tonic-gate        unless defined $$self{center};
326*0Sstevel@tonic-gate    $$self{indent} = 4 unless defined $$self{indent};
327*0Sstevel@tonic-gate
328*0Sstevel@tonic-gate    # We used to try first to get the version number from a local binary, but
329*0Sstevel@tonic-gate    # we shouldn't need that any more.  Get the version from the running Perl.
330*0Sstevel@tonic-gate    # Work a little magic to handle subversions correctly under both the
331*0Sstevel@tonic-gate    # pre-5.6 and the post-5.6 version numbering schemes.
332*0Sstevel@tonic-gate    if (!defined $$self{release}) {
333*0Sstevel@tonic-gate        my @version = ($] =~ /^(\d+)\.(\d{3})(\d{0,3})$/);
334*0Sstevel@tonic-gate        $version[2] ||= 0;
335*0Sstevel@tonic-gate        $version[2] *= 10 ** (3 - length $version[2]);
336*0Sstevel@tonic-gate        for (@version) { $_ += 0 }
337*0Sstevel@tonic-gate        $$self{release} = 'perl v' . join ('.', @version);
338*0Sstevel@tonic-gate    }
339*0Sstevel@tonic-gate
340*0Sstevel@tonic-gate    # Double quotes in things that will be quoted.
341*0Sstevel@tonic-gate    for (qw/center date release/) {
342*0Sstevel@tonic-gate        $$self{$_} =~ s/\"/\"\"/g if $$self{$_};
343*0Sstevel@tonic-gate    }
344*0Sstevel@tonic-gate
345*0Sstevel@tonic-gate    # Figure out what quotes we'll be using for C<> text.
346*0Sstevel@tonic-gate    $$self{quotes} ||= '"';
347*0Sstevel@tonic-gate    if ($$self{quotes} eq 'none') {
348*0Sstevel@tonic-gate        $$self{LQUOTE} = $$self{RQUOTE} = '';
349*0Sstevel@tonic-gate    } elsif (length ($$self{quotes}) == 1) {
350*0Sstevel@tonic-gate        $$self{LQUOTE} = $$self{RQUOTE} = $$self{quotes};
351*0Sstevel@tonic-gate    } elsif ($$self{quotes} =~ /^(.)(.)$/
352*0Sstevel@tonic-gate             || $$self{quotes} =~ /^(..)(..)$/) {
353*0Sstevel@tonic-gate        $$self{LQUOTE} = $1;
354*0Sstevel@tonic-gate        $$self{RQUOTE} = $2;
355*0Sstevel@tonic-gate    } else {
356*0Sstevel@tonic-gate        croak qq(Invalid quote specification "$$self{quotes}");
357*0Sstevel@tonic-gate    }
358*0Sstevel@tonic-gate
359*0Sstevel@tonic-gate    # Double the first quote; note that this should not be s///g as two double
360*0Sstevel@tonic-gate    # quotes is represented in *roff as three double quotes, not four.  Weird,
361*0Sstevel@tonic-gate    # I know.
362*0Sstevel@tonic-gate    $$self{LQUOTE} =~ s/\"/\"\"/;
363*0Sstevel@tonic-gate    $$self{RQUOTE} =~ s/\"/\"\"/;
364*0Sstevel@tonic-gate
365*0Sstevel@tonic-gate    $self->SUPER::initialize;
366*0Sstevel@tonic-gate}
367*0Sstevel@tonic-gate
368*0Sstevel@tonic-gate# For each document we process, output the preamble first.
369*0Sstevel@tonic-gatesub begin_pod {
370*0Sstevel@tonic-gate    my $self = shift;
371*0Sstevel@tonic-gate
372*0Sstevel@tonic-gate    # Try to figure out the name and section from the file name.
373*0Sstevel@tonic-gate    my $section = $$self{section} || 1;
374*0Sstevel@tonic-gate    my $name = $$self{name};
375*0Sstevel@tonic-gate    if (!defined $name) {
376*0Sstevel@tonic-gate        $name = $self->input_file;
377*0Sstevel@tonic-gate        $section = 3 if (!$$self{section} && $name =~ /\.pm\z/i);
378*0Sstevel@tonic-gate        $name =~ s/\.p(od|[lm])\z//i;
379*0Sstevel@tonic-gate        if ($section !~ /^3/) {
380*0Sstevel@tonic-gate            require File::Basename;
381*0Sstevel@tonic-gate            $name = uc File::Basename::basename ($name);
382*0Sstevel@tonic-gate        } else {
383*0Sstevel@tonic-gate            # Assume that we're dealing with a module.  We want to figure out
384*0Sstevel@tonic-gate            # the full module name from the path to the file, but we don't
385*0Sstevel@tonic-gate            # want to include too much of the path into the module name.  Lose
386*0Sstevel@tonic-gate            # everything up to the first of:
387*0Sstevel@tonic-gate            #
388*0Sstevel@tonic-gate            #     */lib/*perl*/         standard or site_perl module
389*0Sstevel@tonic-gate            #     */*perl*/lib/         from -Dprefix=/opt/perl
390*0Sstevel@tonic-gate            #     */*perl*/             random module hierarchy
391*0Sstevel@tonic-gate            #
392*0Sstevel@tonic-gate            # which works.  Also strip off a leading site or site_perl
393*0Sstevel@tonic-gate            # component, any OS-specific component, and any version number
394*0Sstevel@tonic-gate            # component, and strip off an initial component of "lib" or
395*0Sstevel@tonic-gate            # "blib/lib" since that's what ExtUtils::MakeMaker creates.
396*0Sstevel@tonic-gate            # splitdir requires at least File::Spec 0.8.
397*0Sstevel@tonic-gate            require File::Spec;
398*0Sstevel@tonic-gate            my ($volume, $dirs, $file) = File::Spec->splitpath ($name);
399*0Sstevel@tonic-gate            my @dirs = File::Spec->splitdir ($dirs);
400*0Sstevel@tonic-gate            my $cut = 0;
401*0Sstevel@tonic-gate            my $i;
402*0Sstevel@tonic-gate            for ($i = 0; $i < scalar @dirs; $i++) {
403*0Sstevel@tonic-gate                if ($dirs[$i] eq 'lib' && $dirs[$i + 1] =~ /perl/) {
404*0Sstevel@tonic-gate                    $cut = $i + 2;
405*0Sstevel@tonic-gate                    last;
406*0Sstevel@tonic-gate                } elsif ($dirs[$i] =~ /perl/) {
407*0Sstevel@tonic-gate                    $cut = $i + 1;
408*0Sstevel@tonic-gate                    $cut++ if $dirs[$i + 1] eq 'lib';
409*0Sstevel@tonic-gate                    last;
410*0Sstevel@tonic-gate                }
411*0Sstevel@tonic-gate            }
412*0Sstevel@tonic-gate            if ($cut > 0) {
413*0Sstevel@tonic-gate                splice (@dirs, 0, $cut);
414*0Sstevel@tonic-gate                shift @dirs if ($dirs[0] =~ /^site(_perl)?$/);
415*0Sstevel@tonic-gate                shift @dirs if ($dirs[0] =~ /^[\d.]+$/);
416*0Sstevel@tonic-gate                shift @dirs if ($dirs[0] =~ /^(.*-$^O|$^O-.*|$^O)$/);
417*0Sstevel@tonic-gate            }
418*0Sstevel@tonic-gate            shift @dirs if $dirs[0] eq 'lib';
419*0Sstevel@tonic-gate            splice (@dirs, 0, 2) if ($dirs[0] eq 'blib' && $dirs[1] eq 'lib');
420*0Sstevel@tonic-gate
421*0Sstevel@tonic-gate            # Remove empty directories when building the module name; they
422*0Sstevel@tonic-gate            # occur too easily on Unix by doubling slashes.
423*0Sstevel@tonic-gate            $name = join ('::', (grep { $_ ? $_ : () } @dirs), $file);
424*0Sstevel@tonic-gate        }
425*0Sstevel@tonic-gate    }
426*0Sstevel@tonic-gate
427*0Sstevel@tonic-gate    # If $name contains spaces, quote it; this mostly comes up in the case of
428*0Sstevel@tonic-gate    # input from stdin.
429*0Sstevel@tonic-gate    $name = '"' . $name . '"' if ($name =~ /\s/);
430*0Sstevel@tonic-gate
431*0Sstevel@tonic-gate    # Modification date header.  Try to use the modification time of our
432*0Sstevel@tonic-gate    # input.
433*0Sstevel@tonic-gate    if (!defined $$self{date}) {
434*0Sstevel@tonic-gate        my $time = (stat $self->input_file)[9] || time;
435*0Sstevel@tonic-gate        my ($day, $month, $year) = (localtime $time)[3,4,5];
436*0Sstevel@tonic-gate        $month++;
437*0Sstevel@tonic-gate        $year += 1900;
438*0Sstevel@tonic-gate        $$self{date} = sprintf ('%4d-%02d-%02d', $year, $month, $day);
439*0Sstevel@tonic-gate    }
440*0Sstevel@tonic-gate
441*0Sstevel@tonic-gate    # Now, print out the preamble and the title.  The meaning of the arguments
442*0Sstevel@tonic-gate    # to .TH unfortunately vary by system; some systems consider the fourth
443*0Sstevel@tonic-gate    # argument to be a "source" and others use it as a version number.
444*0Sstevel@tonic-gate    # Generally it's just presented as the left-side footer, though, so it
445*0Sstevel@tonic-gate    # doesn't matter too much if a particular system gives it another
446*0Sstevel@tonic-gate    # interpretation.
447*0Sstevel@tonic-gate    #
448*0Sstevel@tonic-gate    # The order of date and release used to be reversed in older versions of
449*0Sstevel@tonic-gate    # this module, but this order is correct for both Solaris and Linux.
450*0Sstevel@tonic-gate    local $_ = $PREAMBLE;
451*0Sstevel@tonic-gate    s/\@CFONT\@/$$self{fixed}/;
452*0Sstevel@tonic-gate    s/\@LQUOTE\@/$$self{LQUOTE}/;
453*0Sstevel@tonic-gate    s/\@RQUOTE\@/$$self{RQUOTE}/;
454*0Sstevel@tonic-gate    chomp $_;
455*0Sstevel@tonic-gate    my $pversion = $Pod::Parser::VERSION;
456*0Sstevel@tonic-gate    print { $self->output_handle } <<"----END OF HEADER----";
457*0Sstevel@tonic-gate.\\" Automatically generated by Pod::Man v$VERSION, Pod::Parser v$pversion
458*0Sstevel@tonic-gate.\\"
459*0Sstevel@tonic-gate.\\" Standard preamble:
460*0Sstevel@tonic-gate.\\" ========================================================================
461*0Sstevel@tonic-gate$_
462*0Sstevel@tonic-gate.\\" ========================================================================
463*0Sstevel@tonic-gate.\\"
464*0Sstevel@tonic-gate.IX Title "$name $section"
465*0Sstevel@tonic-gate.TH $name $section "$$self{date}" "$$self{release}" "$$self{center}"
466*0Sstevel@tonic-gate----END OF HEADER----
467*0Sstevel@tonic-gate
468*0Sstevel@tonic-gate    # Initialize a few per-file variables.
469*0Sstevel@tonic-gate    $$self{INDENT}    = 0;      # Current indentation level.
470*0Sstevel@tonic-gate    $$self{INDENTS}   = [];     # Stack of indentations.
471*0Sstevel@tonic-gate    $$self{INDEX}     = [];     # Index keys waiting to be printed.
472*0Sstevel@tonic-gate    $$self{IN_NAME}   = 0;      # Whether processing the NAME section.
473*0Sstevel@tonic-gate    $$self{ITEMS}     = 0;      # The number of consecutive =items.
474*0Sstevel@tonic-gate    $$self{ITEMTYPES} = [];     # Stack of =item types, one per list.
475*0Sstevel@tonic-gate    $$self{SHIFTWAIT} = 0;      # Whether there is a shift waiting.
476*0Sstevel@tonic-gate    $$self{SHIFTS}    = [];     # Stack of .RS shifts.
477*0Sstevel@tonic-gate}
478*0Sstevel@tonic-gate
479*0Sstevel@tonic-gate
480*0Sstevel@tonic-gate##############################################################################
481*0Sstevel@tonic-gate# Core overrides
482*0Sstevel@tonic-gate##############################################################################
483*0Sstevel@tonic-gate
484*0Sstevel@tonic-gate# Called for each command paragraph.  Gets the command, the associated
485*0Sstevel@tonic-gate# paragraph, the line number, and a Pod::Paragraph object.  Just dispatches
486*0Sstevel@tonic-gate# the command to a method named the same as the command.  =cut is handled
487*0Sstevel@tonic-gate# internally by Pod::Parser.
488*0Sstevel@tonic-gatesub command {
489*0Sstevel@tonic-gate    my $self = shift;
490*0Sstevel@tonic-gate    my $command = shift;
491*0Sstevel@tonic-gate    return if $command eq 'pod';
492*0Sstevel@tonic-gate    return if ($$self{EXCLUDE} && $command ne 'end');
493*0Sstevel@tonic-gate    if ($self->can ('cmd_' . $command)) {
494*0Sstevel@tonic-gate        $command = 'cmd_' . $command;
495*0Sstevel@tonic-gate        $self->$command (@_);
496*0Sstevel@tonic-gate    } else {
497*0Sstevel@tonic-gate        my ($text, $line, $paragraph) = @_;
498*0Sstevel@tonic-gate        my $file;
499*0Sstevel@tonic-gate        ($file, $line) = $paragraph->file_line;
500*0Sstevel@tonic-gate        $text =~ s/\n+\z//;
501*0Sstevel@tonic-gate        $text = " $text" if ($text =~ /^\S/);
502*0Sstevel@tonic-gate        warn qq($file:$line: Unknown command paragraph "=$command$text"\n);
503*0Sstevel@tonic-gate        return;
504*0Sstevel@tonic-gate    }
505*0Sstevel@tonic-gate}
506*0Sstevel@tonic-gate
507*0Sstevel@tonic-gate# Called for a verbatim paragraph.  Gets the paragraph, the line number, and a
508*0Sstevel@tonic-gate# Pod::Paragraph object.  Rofficate backslashes, untabify, put a zero-width
509*0Sstevel@tonic-gate# character at the beginning of each line to protect against commands, and
510*0Sstevel@tonic-gate# wrap in .Vb/.Ve.
511*0Sstevel@tonic-gatesub verbatim {
512*0Sstevel@tonic-gate    my $self = shift;
513*0Sstevel@tonic-gate    return if $$self{EXCLUDE};
514*0Sstevel@tonic-gate    local $_ = shift;
515*0Sstevel@tonic-gate    return if /^\s+$/;
516*0Sstevel@tonic-gate    s/\s+$/\n/;
517*0Sstevel@tonic-gate    my $lines = tr/\n/\n/;
518*0Sstevel@tonic-gate    1 while s/^(.*?)(\t+)/$1 . ' ' x (length ($2) * 8 - length ($1) % 8)/me;
519*0Sstevel@tonic-gate    s/\\/\\e/g;
520*0Sstevel@tonic-gate    s/^(\s*\S)/'\&' . $1/gme;
521*0Sstevel@tonic-gate    $self->makespace;
522*0Sstevel@tonic-gate    $self->output (".Vb $lines\n$_.Ve\n");
523*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 1;
524*0Sstevel@tonic-gate}
525*0Sstevel@tonic-gate
526*0Sstevel@tonic-gate# Called for a regular text block.  Gets the paragraph, the line number, and a
527*0Sstevel@tonic-gate# Pod::Paragraph object.  Perform interpolation and output the results.
528*0Sstevel@tonic-gatesub textblock {
529*0Sstevel@tonic-gate    my $self = shift;
530*0Sstevel@tonic-gate    return if $$self{EXCLUDE};
531*0Sstevel@tonic-gate    $self->output ($_[0]), return if $$self{VERBATIM};
532*0Sstevel@tonic-gate
533*0Sstevel@tonic-gate    # Parse the tree.  collapse knows about references to scalars as well as
534*0Sstevel@tonic-gate    # scalars and does the right thing with them.  Tidy up any trailing
535*0Sstevel@tonic-gate    # whitespace.
536*0Sstevel@tonic-gate    my $text = shift;
537*0Sstevel@tonic-gate    $text = $self->parse ($text, @_);
538*0Sstevel@tonic-gate    $text =~ s/\n\s*$/\n/;
539*0Sstevel@tonic-gate
540*0Sstevel@tonic-gate    # Output the paragraph.  We also have to handle =over without =item.  If
541*0Sstevel@tonic-gate    # there's an =over without =item, SHIFTWAIT will be set, and we need to
542*0Sstevel@tonic-gate    # handle creation of the indent here.  Add the shift to SHIFTS so that it
543*0Sstevel@tonic-gate    # will be cleaned up on =back.
544*0Sstevel@tonic-gate    $self->makespace;
545*0Sstevel@tonic-gate    if ($$self{SHIFTWAIT}) {
546*0Sstevel@tonic-gate        $self->output (".RS $$self{INDENT}\n");
547*0Sstevel@tonic-gate        push (@{ $$self{SHIFTS} }, $$self{INDENT});
548*0Sstevel@tonic-gate        $$self{SHIFTWAIT} = 0;
549*0Sstevel@tonic-gate    }
550*0Sstevel@tonic-gate    $self->output (protect $self->textmapfonts ($text));
551*0Sstevel@tonic-gate    $self->outindex;
552*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 1;
553*0Sstevel@tonic-gate}
554*0Sstevel@tonic-gate
555*0Sstevel@tonic-gate# Called for a formatting code.  Takes a Pod::InteriorSequence object and
556*0Sstevel@tonic-gate# returns a reference to a scalar.  This scalar is the final formatted text.
557*0Sstevel@tonic-gate# It's returned as a reference to an array so that other formatting codes
558*0Sstevel@tonic-gate# above us know that the text has already been processed.
559*0Sstevel@tonic-gatesub sequence {
560*0Sstevel@tonic-gate    my ($self, $seq) = @_;
561*0Sstevel@tonic-gate    my $command = $seq->cmd_name;
562*0Sstevel@tonic-gate
563*0Sstevel@tonic-gate    # We have to defer processing of the inside of an L<> formatting code.  If
564*0Sstevel@tonic-gate    # this code is nested inside an L<> code, return the literal raw text of
565*0Sstevel@tonic-gate    # it.
566*0Sstevel@tonic-gate    my $parent = $seq->nested;
567*0Sstevel@tonic-gate    while (defined $parent) {
568*0Sstevel@tonic-gate        return $seq->raw_text if ($parent->cmd_name eq 'L');
569*0Sstevel@tonic-gate        $parent = $parent->nested;
570*0Sstevel@tonic-gate    }
571*0Sstevel@tonic-gate
572*0Sstevel@tonic-gate    # Zero-width characters.
573*0Sstevel@tonic-gate    return [ '\&' ] if ($command eq 'Z');
574*0Sstevel@tonic-gate
575*0Sstevel@tonic-gate    # C<>, L<>, X<>, and E<> don't apply guesswork to their contents.  C<>
576*0Sstevel@tonic-gate    # needs some additional special handling.
577*0Sstevel@tonic-gate    my $literal = ($command =~ /^[CELX]$/);
578*0Sstevel@tonic-gate    local $_ = $self->collapse ($seq->parse_tree, $literal, $command eq 'C');
579*0Sstevel@tonic-gate
580*0Sstevel@tonic-gate    # Handle E<> escapes.  Numeric escapes that match one of the supported ISO
581*0Sstevel@tonic-gate    # 8859-1 characters don't work at present.
582*0Sstevel@tonic-gate    if ($command eq 'E') {
583*0Sstevel@tonic-gate        if (/^\d+$/) {
584*0Sstevel@tonic-gate            return [ chr ($_) ];
585*0Sstevel@tonic-gate        } elsif (exists $ESCAPES{$_}) {
586*0Sstevel@tonic-gate            return [ $ESCAPES{$_} ];
587*0Sstevel@tonic-gate        } else {
588*0Sstevel@tonic-gate            my ($file, $line) = $seq->file_line;
589*0Sstevel@tonic-gate            warn "$file:$line: Unknown escape E<$_>\n";
590*0Sstevel@tonic-gate            return [ "E<$_>" ];
591*0Sstevel@tonic-gate        }
592*0Sstevel@tonic-gate    }
593*0Sstevel@tonic-gate
594*0Sstevel@tonic-gate    # For all the other codes, empty content produces no output.
595*0Sstevel@tonic-gate    return '' if $_ eq '';
596*0Sstevel@tonic-gate
597*0Sstevel@tonic-gate    # Handle simple formatting codes.
598*0Sstevel@tonic-gate    if ($command eq 'B') {
599*0Sstevel@tonic-gate        return [ '\f(BS' . $_ . '\f(BE' ];
600*0Sstevel@tonic-gate    } elsif ($command eq 'F' || $command eq 'I') {
601*0Sstevel@tonic-gate        return [ '\f(IS' . $_ . '\f(IE' ];
602*0Sstevel@tonic-gate    } elsif ($command eq 'C') {
603*0Sstevel@tonic-gate        return [ $self->quote_literal ($_) ];
604*0Sstevel@tonic-gate    }
605*0Sstevel@tonic-gate
606*0Sstevel@tonic-gate    # Handle links.
607*0Sstevel@tonic-gate    if ($command eq 'L') {
608*0Sstevel@tonic-gate        my ($text, $type) = (parselink ($_))[1,4];
609*0Sstevel@tonic-gate        return '' unless $text;
610*0Sstevel@tonic-gate        my ($file, $line) = $seq->file_line;
611*0Sstevel@tonic-gate        $text = $self->parse ($text, $line);
612*0Sstevel@tonic-gate        $text = '<' . $text . '>' if $type eq 'url';
613*0Sstevel@tonic-gate        return [ $text ];
614*0Sstevel@tonic-gate    }
615*0Sstevel@tonic-gate
616*0Sstevel@tonic-gate    # Whitespace protection replaces whitespace with "\ ".
617*0Sstevel@tonic-gate    if ($command eq 'S') {
618*0Sstevel@tonic-gate        s/\s+/\\ /g;
619*0Sstevel@tonic-gate        return [ $_ ];
620*0Sstevel@tonic-gate    }
621*0Sstevel@tonic-gate
622*0Sstevel@tonic-gate    # Add an index entry to the list of ones waiting to be output.
623*0Sstevel@tonic-gate    if ($command eq 'X') {
624*0Sstevel@tonic-gate        push (@{ $$self{INDEX} }, $_);
625*0Sstevel@tonic-gate        return '';
626*0Sstevel@tonic-gate    }
627*0Sstevel@tonic-gate
628*0Sstevel@tonic-gate    # Anything else is unknown.
629*0Sstevel@tonic-gate    my ($file, $line) = $seq->file_line;
630*0Sstevel@tonic-gate    warn "$file:$line: Unknown formatting code $command<$_>\n";
631*0Sstevel@tonic-gate}
632*0Sstevel@tonic-gate
633*0Sstevel@tonic-gate
634*0Sstevel@tonic-gate##############################################################################
635*0Sstevel@tonic-gate# Command paragraphs
636*0Sstevel@tonic-gate##############################################################################
637*0Sstevel@tonic-gate
638*0Sstevel@tonic-gate# All command paragraphs take the paragraph and the line number.
639*0Sstevel@tonic-gate
640*0Sstevel@tonic-gate# First level heading.  We can't output .IX in the NAME section due to a bug
641*0Sstevel@tonic-gate# in some versions of catman, so don't output a .IX for that section.  .SH
642*0Sstevel@tonic-gate# already uses small caps, so remove \s1 and \s-1.  Maintain IN_NAME as
643*0Sstevel@tonic-gate# appropriate, but don't leave it set while calling parse() so as to not
644*0Sstevel@tonic-gate# override guesswork on section headings after NAME.
645*0Sstevel@tonic-gatesub cmd_head1 {
646*0Sstevel@tonic-gate    my $self = shift;
647*0Sstevel@tonic-gate    $$self{IN_NAME} = 0;
648*0Sstevel@tonic-gate    local $_ = $self->parse (@_);
649*0Sstevel@tonic-gate    s/\s+$//;
650*0Sstevel@tonic-gate    s/\\s-?\d//g;
651*0Sstevel@tonic-gate    s/\s*\n\s*/ /g;
652*0Sstevel@tonic-gate    if ($$self{ITEMS} > 1) {
653*0Sstevel@tonic-gate        $$self{ITEMS} = 0;
654*0Sstevel@tonic-gate        $self->output (".PD\n");
655*0Sstevel@tonic-gate    }
656*0Sstevel@tonic-gate    $self->output ($self->switchquotes ('.SH', $self->mapfonts ($_)));
657*0Sstevel@tonic-gate    $self->outindex (($_ eq 'NAME') ? () : ('Header', $_));
658*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 0;
659*0Sstevel@tonic-gate    $$self{IN_NAME} = ($_ eq 'NAME');
660*0Sstevel@tonic-gate}
661*0Sstevel@tonic-gate
662*0Sstevel@tonic-gate# Second level heading.
663*0Sstevel@tonic-gatesub cmd_head2 {
664*0Sstevel@tonic-gate    my $self = shift;
665*0Sstevel@tonic-gate    local $_ = $self->parse (@_);
666*0Sstevel@tonic-gate    s/\s+$//;
667*0Sstevel@tonic-gate    s/\s*\n\s*/ /g;
668*0Sstevel@tonic-gate    if ($$self{ITEMS} > 1) {
669*0Sstevel@tonic-gate        $$self{ITEMS} = 0;
670*0Sstevel@tonic-gate        $self->output (".PD\n");
671*0Sstevel@tonic-gate    }
672*0Sstevel@tonic-gate    $self->output ($self->switchquotes ('.Sh', $self->mapfonts ($_)));
673*0Sstevel@tonic-gate    $self->outindex ('Subsection', $_);
674*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 0;
675*0Sstevel@tonic-gate}
676*0Sstevel@tonic-gate
677*0Sstevel@tonic-gate# Third level heading.
678*0Sstevel@tonic-gatesub cmd_head3 {
679*0Sstevel@tonic-gate    my $self = shift;
680*0Sstevel@tonic-gate    local $_ = $self->parse (@_);
681*0Sstevel@tonic-gate    s/\s+$//;
682*0Sstevel@tonic-gate    s/\s*\n\s*/ /g;
683*0Sstevel@tonic-gate    if ($$self{ITEMS} > 1) {
684*0Sstevel@tonic-gate        $$self{ITEMS} = 0;
685*0Sstevel@tonic-gate        $self->output (".PD\n");
686*0Sstevel@tonic-gate    }
687*0Sstevel@tonic-gate    $self->makespace;
688*0Sstevel@tonic-gate    $self->output ($self->textmapfonts ('\f(IS' . $_ . '\f(IE') . "\n");
689*0Sstevel@tonic-gate    $self->outindex ('Subsection', $_);
690*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 1;
691*0Sstevel@tonic-gate}
692*0Sstevel@tonic-gate
693*0Sstevel@tonic-gate# Fourth level heading.
694*0Sstevel@tonic-gatesub cmd_head4 {
695*0Sstevel@tonic-gate    my $self = shift;
696*0Sstevel@tonic-gate    local $_ = $self->parse (@_);
697*0Sstevel@tonic-gate    s/\s+$//;
698*0Sstevel@tonic-gate    s/\s*\n\s*/ /g;
699*0Sstevel@tonic-gate    if ($$self{ITEMS} > 1) {
700*0Sstevel@tonic-gate        $$self{ITEMS} = 0;
701*0Sstevel@tonic-gate        $self->output (".PD\n");
702*0Sstevel@tonic-gate    }
703*0Sstevel@tonic-gate    $self->makespace;
704*0Sstevel@tonic-gate    $self->output ($self->textmapfonts ($_) . "\n");
705*0Sstevel@tonic-gate    $self->outindex ('Subsection', $_);
706*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 1;
707*0Sstevel@tonic-gate}
708*0Sstevel@tonic-gate
709*0Sstevel@tonic-gate# Start a list.  For indents after the first, wrap the outside indent in .RS
710*0Sstevel@tonic-gate# so that hanging paragraph tags will be correct.
711*0Sstevel@tonic-gatesub cmd_over {
712*0Sstevel@tonic-gate    my $self = shift;
713*0Sstevel@tonic-gate    local $_ = shift;
714*0Sstevel@tonic-gate    unless (/^[-+]?\d+\s+$/) { $_ = $$self{indent} }
715*0Sstevel@tonic-gate    if (@{ $$self{SHIFTS} } < @{ $$self{INDENTS} }) {
716*0Sstevel@tonic-gate        $self->output (".RS $$self{INDENT}\n");
717*0Sstevel@tonic-gate        push (@{ $$self{SHIFTS} }, $$self{INDENT});
718*0Sstevel@tonic-gate    }
719*0Sstevel@tonic-gate    push (@{ $$self{INDENTS} }, $$self{INDENT});
720*0Sstevel@tonic-gate    push (@{ $$self{ITEMTYPES} }, 'unknown');
721*0Sstevel@tonic-gate    $$self{INDENT} = ($_ + 0);
722*0Sstevel@tonic-gate    $$self{SHIFTWAIT} = 1;
723*0Sstevel@tonic-gate}
724*0Sstevel@tonic-gate
725*0Sstevel@tonic-gate# End a list.  If we've closed an embedded indent, we've mangled the hanging
726*0Sstevel@tonic-gate# paragraph indent, so temporarily replace it with .RS and set WEIRDINDENT.
727*0Sstevel@tonic-gate# We'll close that .RS at the next =back or =item.
728*0Sstevel@tonic-gatesub cmd_back {
729*0Sstevel@tonic-gate    my $self = shift;
730*0Sstevel@tonic-gate    $$self{INDENT} = pop @{ $$self{INDENTS} };
731*0Sstevel@tonic-gate    if (defined $$self{INDENT}) {
732*0Sstevel@tonic-gate        pop @{ $$self{ITEMTYPES} };
733*0Sstevel@tonic-gate    } else {
734*0Sstevel@tonic-gate        my ($file, $line, $paragraph) = @_;
735*0Sstevel@tonic-gate        ($file, $line) = $paragraph->file_line;
736*0Sstevel@tonic-gate        warn "$file:$line: Unmatched =back\n";
737*0Sstevel@tonic-gate        $$self{INDENT} = 0;
738*0Sstevel@tonic-gate    }
739*0Sstevel@tonic-gate    if (@{ $$self{SHIFTS} } > @{ $$self{INDENTS} }) {
740*0Sstevel@tonic-gate        $self->output (".RE\n");
741*0Sstevel@tonic-gate        pop @{ $$self{SHIFTS} };
742*0Sstevel@tonic-gate    }
743*0Sstevel@tonic-gate    if (@{ $$self{INDENTS} } > 0) {
744*0Sstevel@tonic-gate        $self->output (".RE\n");
745*0Sstevel@tonic-gate        $self->output (".RS $$self{INDENT}\n");
746*0Sstevel@tonic-gate    }
747*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 1;
748*0Sstevel@tonic-gate    $$self{SHIFTWAIT} = 0;
749*0Sstevel@tonic-gate}
750*0Sstevel@tonic-gate
751*0Sstevel@tonic-gate# An individual list item.  Emit an index entry for anything that's
752*0Sstevel@tonic-gate# interesting, but don't emit index entries for things like bullets and
753*0Sstevel@tonic-gate# numbers.  rofficate bullets too while we're at it (so for nice output, use *
754*0Sstevel@tonic-gate# for your lists rather than o or . or - or some other thing).  Newlines in an
755*0Sstevel@tonic-gate# item title are turned into spaces since *roff can't handle them embedded.
756*0Sstevel@tonic-gatesub cmd_item {
757*0Sstevel@tonic-gate    my $self = shift;
758*0Sstevel@tonic-gate    local $_ = $self->parse (@_);
759*0Sstevel@tonic-gate    s/\s+$//;
760*0Sstevel@tonic-gate    s/\s*\n\s*/ /g;
761*0Sstevel@tonic-gate    my $index;
762*0Sstevel@tonic-gate    if (/\w/ && !/^\w[.\)]\s*$/) {
763*0Sstevel@tonic-gate        $index = $_;
764*0Sstevel@tonic-gate        $index =~ s/^\s*[-*+o.]?(?:\s+|\Z)//;
765*0Sstevel@tonic-gate    }
766*0Sstevel@tonic-gate    $_ = '*' unless length ($_) > 0;
767*0Sstevel@tonic-gate    my $type = $$self{ITEMTYPES}[0];
768*0Sstevel@tonic-gate    unless (defined $type) {
769*0Sstevel@tonic-gate        my ($file, $line, $paragraph) = @_;
770*0Sstevel@tonic-gate        ($file, $line) = $paragraph->file_line;
771*0Sstevel@tonic-gate        $type = 'unknown';
772*0Sstevel@tonic-gate    }
773*0Sstevel@tonic-gate    if ($type eq 'unknown') {
774*0Sstevel@tonic-gate        $type = /^\*\s*\Z/ ? 'bullet' : 'text';
775*0Sstevel@tonic-gate        $$self{ITEMTYPES}[0] = $type if $$self{ITEMTYPES}[0];
776*0Sstevel@tonic-gate    }
777*0Sstevel@tonic-gate    s/^\*\s*\Z/\\\(bu/ if $type eq 'bullet';
778*0Sstevel@tonic-gate    if (@{ $$self{SHIFTS} } == @{ $$self{INDENTS} }) {
779*0Sstevel@tonic-gate        $self->output (".RE\n");
780*0Sstevel@tonic-gate        pop @{ $$self{SHIFTS} };
781*0Sstevel@tonic-gate    }
782*0Sstevel@tonic-gate    $_ = $self->textmapfonts ($_);
783*0Sstevel@tonic-gate    $self->output (".PD 0\n") if ($$self{ITEMS} == 1);
784*0Sstevel@tonic-gate    $self->output ($self->switchquotes ('.IP', $_, $$self{INDENT}));
785*0Sstevel@tonic-gate    $self->outindex ($index ? ('Item', $index) : ());
786*0Sstevel@tonic-gate    $$self{NEEDSPACE} = 0;
787*0Sstevel@tonic-gate    $$self{ITEMS}++;
788*0Sstevel@tonic-gate    $$self{SHIFTWAIT} = 0;
789*0Sstevel@tonic-gate}
790*0Sstevel@tonic-gate
791*0Sstevel@tonic-gate# Begin a block for a particular translator.  Setting VERBATIM triggers
792*0Sstevel@tonic-gate# special handling in textblock().
793*0Sstevel@tonic-gatesub cmd_begin {
794*0Sstevel@tonic-gate    my $self = shift;
795*0Sstevel@tonic-gate    local $_ = shift;
796*0Sstevel@tonic-gate    my ($kind) = /^(\S+)/ or return;
797*0Sstevel@tonic-gate    if ($kind eq 'man' || $kind eq 'roff') {
798*0Sstevel@tonic-gate        $$self{VERBATIM} = 1;
799*0Sstevel@tonic-gate    } else {
800*0Sstevel@tonic-gate        $$self{EXCLUDE} = 1;
801*0Sstevel@tonic-gate    }
802*0Sstevel@tonic-gate}
803*0Sstevel@tonic-gate
804*0Sstevel@tonic-gate# End a block for a particular translator.  We assume that all =begin/=end
805*0Sstevel@tonic-gate# pairs are properly closed.
806*0Sstevel@tonic-gatesub cmd_end {
807*0Sstevel@tonic-gate    my $self = shift;
808*0Sstevel@tonic-gate    $$self{EXCLUDE} = 0;
809*0Sstevel@tonic-gate    $$self{VERBATIM} = 0;
810*0Sstevel@tonic-gate}
811*0Sstevel@tonic-gate
812*0Sstevel@tonic-gate# One paragraph for a particular translator.  Ignore it unless it's intended
813*0Sstevel@tonic-gate# for man or roff, in which case we output it verbatim.
814*0Sstevel@tonic-gatesub cmd_for {
815*0Sstevel@tonic-gate    my $self = shift;
816*0Sstevel@tonic-gate    local $_ = shift;
817*0Sstevel@tonic-gate    return unless s/^(?:man|roff)\b[ \t]*\n?//;
818*0Sstevel@tonic-gate    $self->output ($_);
819*0Sstevel@tonic-gate}
820*0Sstevel@tonic-gate
821*0Sstevel@tonic-gate
822*0Sstevel@tonic-gate##############################################################################
823*0Sstevel@tonic-gate# Escaping and fontification
824*0Sstevel@tonic-gate##############################################################################
825*0Sstevel@tonic-gate
826*0Sstevel@tonic-gate# At this point, we'll have embedded font codes of the form \f(<font>[SE]
827*0Sstevel@tonic-gate# where <font> is one of B, I, or F.  Turn those into the right font start or
828*0Sstevel@tonic-gate# end codes.  The old pod2man didn't get B<someI<thing> else> right; after I<>
829*0Sstevel@tonic-gate# it switched back to normal text rather than bold.  We take care of this by
830*0Sstevel@tonic-gate# using variables as a combined pointer to our current font sequence, and set
831*0Sstevel@tonic-gate# each to the number of current nestings of start tags for that font.  Use
832*0Sstevel@tonic-gate# them as a vector to look up what font sequence to use.
833*0Sstevel@tonic-gate#
834*0Sstevel@tonic-gate# \fP changes to the previous font, but only one previous font is kept.  We
835*0Sstevel@tonic-gate# don't know what the outside level font is; normally it's R, but if we're
836*0Sstevel@tonic-gate# inside a heading it could be something else.  So arrange things so that the
837*0Sstevel@tonic-gate# outside font is always the "previous" font and end with \fP instead of \fR.
838*0Sstevel@tonic-gate# Idea from Zack Weinberg.
839*0Sstevel@tonic-gatesub mapfonts {
840*0Sstevel@tonic-gate    my $self = shift;
841*0Sstevel@tonic-gate    local $_ = shift;
842*0Sstevel@tonic-gate
843*0Sstevel@tonic-gate    my ($fixed, $bold, $italic) = (0, 0, 0);
844*0Sstevel@tonic-gate    my %magic = (F => \$fixed, B => \$bold, I => \$italic);
845*0Sstevel@tonic-gate    my $last = '\fR';
846*0Sstevel@tonic-gate    s { \\f\((.)(.) } {
847*0Sstevel@tonic-gate        my $sequence = '';
848*0Sstevel@tonic-gate        my $f;
849*0Sstevel@tonic-gate        if ($last ne '\fR') { $sequence = '\fP' }
850*0Sstevel@tonic-gate        ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1;
851*0Sstevel@tonic-gate        $f = $$self{FONTS}{($fixed && 1) . ($bold && 1) . ($italic && 1)};
852*0Sstevel@tonic-gate        if ($f eq $last) {
853*0Sstevel@tonic-gate            '';
854*0Sstevel@tonic-gate        } else {
855*0Sstevel@tonic-gate            if ($f ne '\fR') { $sequence .= $f }
856*0Sstevel@tonic-gate            $last = $f;
857*0Sstevel@tonic-gate            $sequence;
858*0Sstevel@tonic-gate        }
859*0Sstevel@tonic-gate    }gxe;
860*0Sstevel@tonic-gate    $_;
861*0Sstevel@tonic-gate}
862*0Sstevel@tonic-gate
863*0Sstevel@tonic-gate# Unfortunately, there is a bug in Solaris 2.6 nroff (not present in GNU
864*0Sstevel@tonic-gate# groff) where the sequence \fB\fP\f(CW\fP leaves the font set to B rather
865*0Sstevel@tonic-gate# than R, presumably because \f(CW doesn't actually do a font change.  To work
866*0Sstevel@tonic-gate# around this, use a separate textmapfonts for text blocks where the default
867*0Sstevel@tonic-gate# font is always R and only use the smart mapfonts for headings.
868*0Sstevel@tonic-gatesub textmapfonts {
869*0Sstevel@tonic-gate    my $self = shift;
870*0Sstevel@tonic-gate    local $_ = shift;
871*0Sstevel@tonic-gate
872*0Sstevel@tonic-gate    my ($fixed, $bold, $italic) = (0, 0, 0);
873*0Sstevel@tonic-gate    my %magic = (F => \$fixed, B => \$bold, I => \$italic);
874*0Sstevel@tonic-gate    s { \\f\((.)(.) } {
875*0Sstevel@tonic-gate        ${ $magic{$1} } += ($2 eq 'S') ? 1 : -1;
876*0Sstevel@tonic-gate        $$self{FONTS}{($fixed && 1) . ($bold && 1) . ($italic && 1)};
877*0Sstevel@tonic-gate    }gxe;
878*0Sstevel@tonic-gate    $_;
879*0Sstevel@tonic-gate}
880*0Sstevel@tonic-gate
881*0Sstevel@tonic-gate
882*0Sstevel@tonic-gate##############################################################################
883*0Sstevel@tonic-gate# *roff-specific parsing and magic
884*0Sstevel@tonic-gate##############################################################################
885*0Sstevel@tonic-gate
886*0Sstevel@tonic-gate# Called instead of parse_text, calls parse_text with the right flags.
887*0Sstevel@tonic-gatesub parse {
888*0Sstevel@tonic-gate    my $self = shift;
889*0Sstevel@tonic-gate    $self->parse_text ({ -expand_seq   => 'sequence',
890*0Sstevel@tonic-gate                         -expand_ptree => 'collapse' }, @_);
891*0Sstevel@tonic-gate}
892*0Sstevel@tonic-gate
893*0Sstevel@tonic-gate# Takes a parse tree, a flag saying whether or not to treat it as literal text
894*0Sstevel@tonic-gate# (not call guesswork on it), and a flag saying whether or not to clean some
895*0Sstevel@tonic-gate# things up for *roff, and returns the concatenation of all of the text
896*0Sstevel@tonic-gate# strings in that parse tree.  If the literal flag isn't true, guesswork()
897*0Sstevel@tonic-gate# will be called on all plain scalars in the parse tree.  Otherwise, if
898*0Sstevel@tonic-gate# collapse is being called on a C<> code, $cleanup should be set to true and
899*0Sstevel@tonic-gate# some additional cleanup will be done.  Assumes that everything in the parse
900*0Sstevel@tonic-gate# tree is either a scalar or a reference to a scalar.
901*0Sstevel@tonic-gatesub collapse {
902*0Sstevel@tonic-gate    my ($self, $ptree, $literal, $cleanup) = @_;
903*0Sstevel@tonic-gate
904*0Sstevel@tonic-gate    # If we're processing the NAME section, don't do normal guesswork.  This
905*0Sstevel@tonic-gate    # is because NAME lines are often extracted by utilities like catman that
906*0Sstevel@tonic-gate    # require plain text and don't understand *roff markup.  We still need to
907*0Sstevel@tonic-gate    # escape backslashes and hyphens for *roff (and catman expects \- instead
908*0Sstevel@tonic-gate    # of -).
909*0Sstevel@tonic-gate    if ($$self{IN_NAME}) {
910*0Sstevel@tonic-gate        $literal = 1;
911*0Sstevel@tonic-gate        $cleanup = 1;
912*0Sstevel@tonic-gate    }
913*0Sstevel@tonic-gate
914*0Sstevel@tonic-gate    # Do the collapse of the parse tree as described above.
915*0Sstevel@tonic-gate    return join ('', map {
916*0Sstevel@tonic-gate        if (ref $_) {
917*0Sstevel@tonic-gate            join ('', @$_);
918*0Sstevel@tonic-gate        } elsif ($literal) {
919*0Sstevel@tonic-gate            if ($cleanup) {
920*0Sstevel@tonic-gate                s/\\/\\e/g;
921*0Sstevel@tonic-gate                s/-/\\-/g;
922*0Sstevel@tonic-gate                s/__/_\\|_/g;
923*0Sstevel@tonic-gate            }
924*0Sstevel@tonic-gate            $_;
925*0Sstevel@tonic-gate        } else {
926*0Sstevel@tonic-gate            $self->guesswork ($_);
927*0Sstevel@tonic-gate        }
928*0Sstevel@tonic-gate    } $ptree->children);
929*0Sstevel@tonic-gate}
930*0Sstevel@tonic-gate
931*0Sstevel@tonic-gate# Takes a text block to perform guesswork on; this is guaranteed not to
932*0Sstevel@tonic-gate# contain any formatting codes.  Returns the text block with remapping done.
933*0Sstevel@tonic-gatesub guesswork {
934*0Sstevel@tonic-gate    my $self = shift;
935*0Sstevel@tonic-gate    local $_ = shift;
936*0Sstevel@tonic-gate
937*0Sstevel@tonic-gate    # rofficate backslashes.
938*0Sstevel@tonic-gate    s/\\/\\e/g;
939*0Sstevel@tonic-gate
940*0Sstevel@tonic-gate    # Ensure double underbars have a tiny space between them.
941*0Sstevel@tonic-gate    s/__/_\\|_/g;
942*0Sstevel@tonic-gate
943*0Sstevel@tonic-gate    # Leave hyphens only if they're part of regular words and there is only
944*0Sstevel@tonic-gate    # one dash at a time.  Leave a dash after the first character as a regular
945*0Sstevel@tonic-gate    # non-breaking dash, but don't let it mark the rest of the word invalid
946*0Sstevel@tonic-gate    # for hyphenation.
947*0Sstevel@tonic-gate    s/-/\\-/g;
948*0Sstevel@tonic-gate    s{
949*0Sstevel@tonic-gate      ( (?:\G|^|\s) [a-zA-Z] ) ( \\- )?
950*0Sstevel@tonic-gate      ( (?: [a-zA-Z]+ \\-)+ )
951*0Sstevel@tonic-gate      ( [a-zA-Z]+ ) (?=\s|\Z)
952*0Sstevel@tonic-gate      \b
953*0Sstevel@tonic-gate     } {
954*0Sstevel@tonic-gate         my ($prefix, $hyphen, $main, $suffix) = ($1, $2, $3, $4);
955*0Sstevel@tonic-gate         $hyphen ||= '';
956*0Sstevel@tonic-gate         $main =~ s/\\-/-/g;
957*0Sstevel@tonic-gate         $prefix . $hyphen . $main . $suffix;
958*0Sstevel@tonic-gate    }egx;
959*0Sstevel@tonic-gate
960*0Sstevel@tonic-gate    # Translate -- into a real em dash if it's used like one.
961*0Sstevel@tonic-gate    s{ (\s) \\-\\- (\s) }                         { $1 . '\*(--' . $2 }egx;
962*0Sstevel@tonic-gate    s{ (\b[a-zA-Z]+) \\-\\- (\s|\Z|[a-zA-Z]+\b) } { $1 . '\*(--' . $2 }egx;
963*0Sstevel@tonic-gate
964*0Sstevel@tonic-gate    # Make all caps a little smaller.  Be careful here, since we don't want to
965*0Sstevel@tonic-gate    # make @ARGV into small caps, nor do we want to fix the MIME in
966*0Sstevel@tonic-gate    # MIME-Version, since it looks weird with the full-height V.
967*0Sstevel@tonic-gate    s{
968*0Sstevel@tonic-gate        ( ^ | [\s\(\"\'\`\[\{<>] )
969*0Sstevel@tonic-gate        ( [A-Z] [A-Z] (?: [/A-Z+:\d_\$&] | \\- )* )
970*0Sstevel@tonic-gate        (?= [\s>\}\]\(\)\'\".?!,;] | \\*\(-- | $ )
971*0Sstevel@tonic-gate    } { $1 . '\s-1' . $2 . '\s0' }egx;
972*0Sstevel@tonic-gate
973*0Sstevel@tonic-gate    # Italize functions in the form func().
974*0Sstevel@tonic-gate    s{
975*0Sstevel@tonic-gate        ( \b | \\s-1 )
976*0Sstevel@tonic-gate        (
977*0Sstevel@tonic-gate            [A-Za-z_] ([:\w]|\\s-?[01])+ \(\)
978*0Sstevel@tonic-gate        )
979*0Sstevel@tonic-gate    } { $1 . '\f(IS' . $2 . '\f(IE' }egx;
980*0Sstevel@tonic-gate
981*0Sstevel@tonic-gate    # func(n) is a reference to a manual page.  Make it \fIfunc\fR\|(n).
982*0Sstevel@tonic-gate    s{
983*0Sstevel@tonic-gate        ( \b | \\s-1 )
984*0Sstevel@tonic-gate        ( [A-Za-z_] (?:[.:\w]|\\-|\\s-?[01])+ )
985*0Sstevel@tonic-gate        (
986*0Sstevel@tonic-gate            \( \d [a-z]* \)
987*0Sstevel@tonic-gate        )
988*0Sstevel@tonic-gate    } { $1 . '\f(IS' . $2 . '\f(IE\|' . $3 }egx;
989*0Sstevel@tonic-gate
990*0Sstevel@tonic-gate    # Convert simple Perl variable references to a fixed-width font.
991*0Sstevel@tonic-gate    s{
992*0Sstevel@tonic-gate        ( \s+ )
993*0Sstevel@tonic-gate        ( [\$\@%] [\w:]+ )
994*0Sstevel@tonic-gate        (?! \( )
995*0Sstevel@tonic-gate    } { $1 . '\f(FS' . $2 . '\f(FE'}egx;
996*0Sstevel@tonic-gate
997*0Sstevel@tonic-gate    # Fix up double quotes.
998*0Sstevel@tonic-gate    s{ \" ([^\"]+) \" } { '\*(L"' . $1 . '\*(R"' }egx;
999*0Sstevel@tonic-gate
1000*0Sstevel@tonic-gate    # Make C++ into \*(C+, which is a squinched version.
1001*0Sstevel@tonic-gate    s{ \b C\+\+ } {\\*\(C+}gx;
1002*0Sstevel@tonic-gate
1003*0Sstevel@tonic-gate    # All done.
1004*0Sstevel@tonic-gate    $_;
1005*0Sstevel@tonic-gate}
1006*0Sstevel@tonic-gate
1007*0Sstevel@tonic-gate# Handles C<> text, deciding whether to put \*C` around it or not.  This is a
1008*0Sstevel@tonic-gate# whole bunch of messy heuristics to try to avoid overquoting, originally from
1009*0Sstevel@tonic-gate# Barrie Slaymaker.  This largely duplicates similar code in Pod::Text.
1010*0Sstevel@tonic-gatesub quote_literal {
1011*0Sstevel@tonic-gate    my $self = shift;
1012*0Sstevel@tonic-gate    local $_ = shift;
1013*0Sstevel@tonic-gate
1014*0Sstevel@tonic-gate    # A regex that matches the portion of a variable reference that's the
1015*0Sstevel@tonic-gate    # array or hash index, separated out just because we want to use it in
1016*0Sstevel@tonic-gate    # several places in the following regex.
1017*0Sstevel@tonic-gate    my $index = '(?: \[.*\] | \{.*\} )?';
1018*0Sstevel@tonic-gate
1019*0Sstevel@tonic-gate    # Check for things that we don't want to quote, and if we find any of
1020*0Sstevel@tonic-gate    # them, return the string with just a font change and no quoting.
1021*0Sstevel@tonic-gate    m{
1022*0Sstevel@tonic-gate      ^\s*
1023*0Sstevel@tonic-gate      (?:
1024*0Sstevel@tonic-gate         ( [\'\`\"] ) .* \1                             # already quoted
1025*0Sstevel@tonic-gate       | \` .* \'                                       # `quoted'
1026*0Sstevel@tonic-gate       | \$+ [\#^]? \S $index                           # special ($^Foo, $")
1027*0Sstevel@tonic-gate       | [\$\@%&*]+ \#? [:\'\w]+ $index                 # plain var or func
1028*0Sstevel@tonic-gate       | [\$\@%&*]* [:\'\w]+ (?: -> )? \(\s*[^\s,]\s*\) # 0/1-arg func call
1029*0Sstevel@tonic-gate       | [+-]? ( \d[\d.]* | \.\d+ ) (?: [eE][+-]?\d+ )? # a number
1030*0Sstevel@tonic-gate       | 0x [a-fA-F\d]+                                 # a hex constant
1031*0Sstevel@tonic-gate      )
1032*0Sstevel@tonic-gate      \s*\z
1033*0Sstevel@tonic-gate     }xo && return '\f(FS' . $_ . '\f(FE';
1034*0Sstevel@tonic-gate
1035*0Sstevel@tonic-gate    # If we didn't return, go ahead and quote the text.
1036*0Sstevel@tonic-gate    return '\f(FS\*(C`' . $_ . "\\*(C'\\f(FE";
1037*0Sstevel@tonic-gate}
1038*0Sstevel@tonic-gate
1039*0Sstevel@tonic-gate
1040*0Sstevel@tonic-gate##############################################################################
1041*0Sstevel@tonic-gate# Output formatting
1042*0Sstevel@tonic-gate##############################################################################
1043*0Sstevel@tonic-gate
1044*0Sstevel@tonic-gate# Make vertical whitespace.
1045*0Sstevel@tonic-gatesub makespace {
1046*0Sstevel@tonic-gate    my $self = shift;
1047*0Sstevel@tonic-gate    $self->output (".PD\n") if ($$self{ITEMS} > 1);
1048*0Sstevel@tonic-gate    $$self{ITEMS} = 0;
1049*0Sstevel@tonic-gate    $self->output ($$self{INDENT} > 0 ? ".Sp\n" : ".PP\n")
1050*0Sstevel@tonic-gate        if $$self{NEEDSPACE};
1051*0Sstevel@tonic-gate}
1052*0Sstevel@tonic-gate
1053*0Sstevel@tonic-gate# Output any pending index entries, and optionally an index entry given as an
1054*0Sstevel@tonic-gate# argument.  Support multiple index entries in X<> separated by slashes, and
1055*0Sstevel@tonic-gate# strip special escapes from index entries.
1056*0Sstevel@tonic-gatesub outindex {
1057*0Sstevel@tonic-gate    my ($self, $section, $index) = @_;
1058*0Sstevel@tonic-gate    my @entries = map { split m%\s*/\s*% } @{ $$self{INDEX} };
1059*0Sstevel@tonic-gate    return unless ($section || @entries);
1060*0Sstevel@tonic-gate    $$self{INDEX} = [];
1061*0Sstevel@tonic-gate    my @output;
1062*0Sstevel@tonic-gate    if (@entries) {
1063*0Sstevel@tonic-gate        push (@output, [ 'Xref', join (' ', @entries) ]);
1064*0Sstevel@tonic-gate    }
1065*0Sstevel@tonic-gate    if ($section) {
1066*0Sstevel@tonic-gate        $index =~ s/\\-/-/g;
1067*0Sstevel@tonic-gate        $index =~ s/\\(?:s-?\d|.\(..|.)//g;
1068*0Sstevel@tonic-gate        push (@output, [ $section, $index ]);
1069*0Sstevel@tonic-gate    }
1070*0Sstevel@tonic-gate    for (@output) {
1071*0Sstevel@tonic-gate        my ($type, $entry) = @$_;
1072*0Sstevel@tonic-gate        $entry =~ s/\"/\"\"/g;
1073*0Sstevel@tonic-gate        $self->output (".IX $type " . '"' . $entry . '"' . "\n");
1074*0Sstevel@tonic-gate    }
1075*0Sstevel@tonic-gate}
1076*0Sstevel@tonic-gate
1077*0Sstevel@tonic-gate# Output text to the output device.
1078*0Sstevel@tonic-gatesub output { print { $_[0]->output_handle } $_[1] }
1079*0Sstevel@tonic-gate
1080*0Sstevel@tonic-gate# Given a command and a single argument that may or may not contain double
1081*0Sstevel@tonic-gate# quotes, handle double-quote formatting for it.  If there are no double
1082*0Sstevel@tonic-gate# quotes, just return the command followed by the argument in double quotes.
1083*0Sstevel@tonic-gate# If there are double quotes, use an if statement to test for nroff, and for
1084*0Sstevel@tonic-gate# nroff output the command followed by the argument in double quotes with
1085*0Sstevel@tonic-gate# embedded double quotes doubled.  For other formatters, remap paired double
1086*0Sstevel@tonic-gate# quotes to LQUOTE and RQUOTE.
1087*0Sstevel@tonic-gatesub switchquotes {
1088*0Sstevel@tonic-gate    my $self = shift;
1089*0Sstevel@tonic-gate    my $command = shift;
1090*0Sstevel@tonic-gate    local $_ = shift;
1091*0Sstevel@tonic-gate    my $extra = shift;
1092*0Sstevel@tonic-gate    s/\\\*\([LR]\"/\"/g;
1093*0Sstevel@tonic-gate
1094*0Sstevel@tonic-gate    # We also have to deal with \*C` and \*C', which are used to add the
1095*0Sstevel@tonic-gate    # quotes around C<> text, since they may expand to " and if they do this
1096*0Sstevel@tonic-gate    # confuses the .SH macros and the like no end.  Expand them ourselves.
1097*0Sstevel@tonic-gate    # Also separate troff from nroff if there are any fixed-width fonts in use
1098*0Sstevel@tonic-gate    # to work around problems with Solaris nroff.
1099*0Sstevel@tonic-gate    my $c_is_quote = ($$self{LQUOTE} =~ /\"/) || ($$self{RQUOTE} =~ /\"/);
1100*0Sstevel@tonic-gate    my $fixedpat = join ('|', @{ $$self{FONTS} }{'100', '101', '110', '111'});
1101*0Sstevel@tonic-gate    $fixedpat =~ s/\\/\\\\/g;
1102*0Sstevel@tonic-gate    $fixedpat =~ s/\(/\\\(/g;
1103*0Sstevel@tonic-gate    if (/\"/ || /$fixedpat/) {
1104*0Sstevel@tonic-gate        s/\"/\"\"/g;
1105*0Sstevel@tonic-gate        my $nroff = $_;
1106*0Sstevel@tonic-gate        my $troff = $_;
1107*0Sstevel@tonic-gate        $troff =~ s/\"\"([^\"]*)\"\"/\`\`$1\'\'/g;
1108*0Sstevel@tonic-gate        if ($c_is_quote && /\\\*\(C[\'\`]/) {
1109*0Sstevel@tonic-gate            $nroff =~ s/\\\*\(C\`/$$self{LQUOTE}/g;
1110*0Sstevel@tonic-gate            $nroff =~ s/\\\*\(C\'/$$self{RQUOTE}/g;
1111*0Sstevel@tonic-gate            $troff =~ s/\\\*\(C[\'\`]//g;
1112*0Sstevel@tonic-gate        }
1113*0Sstevel@tonic-gate        $nroff = qq("$nroff") . ($extra ? " $extra" : '');
1114*0Sstevel@tonic-gate        $troff = qq("$troff") . ($extra ? " $extra" : '');
1115*0Sstevel@tonic-gate
1116*0Sstevel@tonic-gate        # Work around the Solaris nroff bug where \f(CW\fP leaves the font set
1117*0Sstevel@tonic-gate        # to Roman rather than the actual previous font when used in headings.
1118*0Sstevel@tonic-gate        # troff output may still be broken, but at least we can fix nroff by
1119*0Sstevel@tonic-gate        # just switching the font changes to the non-fixed versions.
1120*0Sstevel@tonic-gate        $nroff =~ s/\Q$$self{FONTS}{100}\E(.*)\\f[PR]/$1/g;
1121*0Sstevel@tonic-gate        $nroff =~ s/\Q$$self{FONTS}{101}\E(.*)\\f([PR])/\\fI$1\\f$2/g;
1122*0Sstevel@tonic-gate        $nroff =~ s/\Q$$self{FONTS}{110}\E(.*)\\f([PR])/\\fB$1\\f$2/g;
1123*0Sstevel@tonic-gate        $nroff =~ s/\Q$$self{FONTS}{111}\E(.*)\\f([PR])/\\f\(BI$1\\f$2/g;
1124*0Sstevel@tonic-gate
1125*0Sstevel@tonic-gate        # Now finally output the command.  Only bother with .ie if the nroff
1126*0Sstevel@tonic-gate        # and troff output isn't the same.
1127*0Sstevel@tonic-gate        if ($nroff ne $troff) {
1128*0Sstevel@tonic-gate            return ".ie n $command $nroff\n.el $command $troff\n";
1129*0Sstevel@tonic-gate        } else {
1130*0Sstevel@tonic-gate            return "$command $nroff\n";
1131*0Sstevel@tonic-gate        }
1132*0Sstevel@tonic-gate    } else {
1133*0Sstevel@tonic-gate        $_ = qq("$_") . ($extra ? " $extra" : '');
1134*0Sstevel@tonic-gate        return "$command $_\n";
1135*0Sstevel@tonic-gate    }
1136*0Sstevel@tonic-gate}
1137*0Sstevel@tonic-gate
1138*0Sstevel@tonic-gate##############################################################################
1139*0Sstevel@tonic-gate# Module return value and documentation
1140*0Sstevel@tonic-gate##############################################################################
1141*0Sstevel@tonic-gate
1142*0Sstevel@tonic-gate1;
1143*0Sstevel@tonic-gate__END__
1144*0Sstevel@tonic-gate
1145*0Sstevel@tonic-gate=head1 NAME
1146*0Sstevel@tonic-gate
1147*0Sstevel@tonic-gatePod::Man - Convert POD data to formatted *roff input
1148*0Sstevel@tonic-gate
1149*0Sstevel@tonic-gate=head1 SYNOPSIS
1150*0Sstevel@tonic-gate
1151*0Sstevel@tonic-gate    use Pod::Man;
1152*0Sstevel@tonic-gate    my $parser = Pod::Man->new (release => $VERSION, section => 8);
1153*0Sstevel@tonic-gate
1154*0Sstevel@tonic-gate    # Read POD from STDIN and write to STDOUT.
1155*0Sstevel@tonic-gate    $parser->parse_from_filehandle;
1156*0Sstevel@tonic-gate
1157*0Sstevel@tonic-gate    # Read POD from file.pod and write to file.1.
1158*0Sstevel@tonic-gate    $parser->parse_from_file ('file.pod', 'file.1');
1159*0Sstevel@tonic-gate
1160*0Sstevel@tonic-gate=head1 DESCRIPTION
1161*0Sstevel@tonic-gate
1162*0Sstevel@tonic-gatePod::Man is a module to convert documentation in the POD format (the
1163*0Sstevel@tonic-gatepreferred language for documenting Perl) into *roff input using the man
1164*0Sstevel@tonic-gatemacro set.  The resulting *roff code is suitable for display on a terminal
1165*0Sstevel@tonic-gateusing L<nroff(1)>, normally via L<man(1)>, or printing using L<troff(1)>.
1166*0Sstevel@tonic-gateIt is conventionally invoked using the driver script B<pod2man>, but it can
1167*0Sstevel@tonic-gatealso be used directly.
1168*0Sstevel@tonic-gate
1169*0Sstevel@tonic-gateAs a derived class from Pod::Parser, Pod::Man supports the same methods and
1170*0Sstevel@tonic-gateinterfaces.  See L<Pod::Parser> for all the details; briefly, one creates a
1171*0Sstevel@tonic-gatenew parser with C<< Pod::Man->new() >> and then calls either
1172*0Sstevel@tonic-gateparse_from_filehandle() or parse_from_file().
1173*0Sstevel@tonic-gate
1174*0Sstevel@tonic-gatenew() can take options, in the form of key/value pairs that control the
1175*0Sstevel@tonic-gatebehavior of the parser.  See below for details.
1176*0Sstevel@tonic-gate
1177*0Sstevel@tonic-gateIf no options are given, Pod::Man uses the name of the input file with any
1178*0Sstevel@tonic-gatetrailing C<.pod>, C<.pm>, or C<.pl> stripped as the man page title, to
1179*0Sstevel@tonic-gatesection 1 unless the file ended in C<.pm> in which case it defaults to
1180*0Sstevel@tonic-gatesection 3, to a centered title of "User Contributed Perl Documentation", to
1181*0Sstevel@tonic-gatea centered footer of the Perl version it is run with, and to a left-hand
1182*0Sstevel@tonic-gatefooter of the modification date of its input (or the current date if given
1183*0Sstevel@tonic-gateSTDIN for input).
1184*0Sstevel@tonic-gate
1185*0Sstevel@tonic-gatePod::Man assumes that your *roff formatters have a fixed-width font named
1186*0Sstevel@tonic-gateCW.  If yours is called something else (like CR), use the C<fixed> option to
1187*0Sstevel@tonic-gatespecify it.  This generally only matters for troff output for printing.
1188*0Sstevel@tonic-gateSimilarly, you can set the fonts used for bold, italic, and bold italic
1189*0Sstevel@tonic-gatefixed-width output.
1190*0Sstevel@tonic-gate
1191*0Sstevel@tonic-gateBesides the obvious pod conversions, Pod::Man also takes care of formatting
1192*0Sstevel@tonic-gatefunc(), func(3), and simple variable references like $foo or @bar so you
1193*0Sstevel@tonic-gatedon't have to use code escapes for them; complex expressions like
1194*0Sstevel@tonic-gateC<$fred{'stuff'}> will still need to be escaped, though.  It also translates
1195*0Sstevel@tonic-gatedashes that aren't used as hyphens into en dashes, makes long dashes--like
1196*0Sstevel@tonic-gatethis--into proper em dashes, fixes "paired quotes," makes C++ look right,
1197*0Sstevel@tonic-gateputs a little space between double underbars, makes ALLCAPS a teeny bit
1198*0Sstevel@tonic-gatesmaller in B<troff>, and escapes stuff that *roff treats as special so that
1199*0Sstevel@tonic-gateyou don't have to.
1200*0Sstevel@tonic-gate
1201*0Sstevel@tonic-gateThe recognized options to new() are as follows.  All options take a single
1202*0Sstevel@tonic-gateargument.
1203*0Sstevel@tonic-gate
1204*0Sstevel@tonic-gate=over 4
1205*0Sstevel@tonic-gate
1206*0Sstevel@tonic-gate=item center
1207*0Sstevel@tonic-gate
1208*0Sstevel@tonic-gateSets the centered page header to use instead of "User Contributed Perl
1209*0Sstevel@tonic-gateDocumentation".
1210*0Sstevel@tonic-gate
1211*0Sstevel@tonic-gate=item date
1212*0Sstevel@tonic-gate
1213*0Sstevel@tonic-gateSets the left-hand footer.  By default, the modification date of the input
1214*0Sstevel@tonic-gatefile will be used, or the current date if stat() can't find that file (the
1215*0Sstevel@tonic-gatecase if the input is from STDIN), and the date will be formatted as
1216*0Sstevel@tonic-gateYYYY-MM-DD.
1217*0Sstevel@tonic-gate
1218*0Sstevel@tonic-gate=item fixed
1219*0Sstevel@tonic-gate
1220*0Sstevel@tonic-gateThe fixed-width font to use for vertabim text and code.  Defaults to CW.
1221*0Sstevel@tonic-gateSome systems may want CR instead.  Only matters for B<troff> output.
1222*0Sstevel@tonic-gate
1223*0Sstevel@tonic-gate=item fixedbold
1224*0Sstevel@tonic-gate
1225*0Sstevel@tonic-gateBold version of the fixed-width font.  Defaults to CB.  Only matters for
1226*0Sstevel@tonic-gateB<troff> output.
1227*0Sstevel@tonic-gate
1228*0Sstevel@tonic-gate=item fixeditalic
1229*0Sstevel@tonic-gate
1230*0Sstevel@tonic-gateItalic version of the fixed-width font (actually, something of a misnomer,
1231*0Sstevel@tonic-gatesince most fixed-width fonts only have an oblique version, not an italic
1232*0Sstevel@tonic-gateversion).  Defaults to CI.  Only matters for B<troff> output.
1233*0Sstevel@tonic-gate
1234*0Sstevel@tonic-gate=item fixedbolditalic
1235*0Sstevel@tonic-gate
1236*0Sstevel@tonic-gateBold italic (probably actually oblique) version of the fixed-width font.
1237*0Sstevel@tonic-gatePod::Man doesn't assume you have this, and defaults to CB.  Some systems
1238*0Sstevel@tonic-gate(such as Solaris) have this font available as CX.  Only matters for B<troff>
1239*0Sstevel@tonic-gateoutput.
1240*0Sstevel@tonic-gate
1241*0Sstevel@tonic-gate=item name
1242*0Sstevel@tonic-gate
1243*0Sstevel@tonic-gateSet the name of the manual page.  Without this option, the manual name is
1244*0Sstevel@tonic-gateset to the uppercased base name of the file being converted unless the
1245*0Sstevel@tonic-gatemanual section is 3, in which case the path is parsed to see if it is a Perl
1246*0Sstevel@tonic-gatemodule path.  If it is, a path like C<.../lib/Pod/Man.pm> is converted into
1247*0Sstevel@tonic-gatea name like C<Pod::Man>.  This option, if given, overrides any automatic
1248*0Sstevel@tonic-gatedetermination of the name.
1249*0Sstevel@tonic-gate
1250*0Sstevel@tonic-gate=item quotes
1251*0Sstevel@tonic-gate
1252*0Sstevel@tonic-gateSets the quote marks used to surround CE<lt>> text.  If the value is a
1253*0Sstevel@tonic-gatesingle character, it is used as both the left and right quote; if it is two
1254*0Sstevel@tonic-gatecharacters, the first character is used as the left quote and the second as
1255*0Sstevel@tonic-gatethe right quoted; and if it is four characters, the first two are used as
1256*0Sstevel@tonic-gatethe left quote and the second two as the right quote.
1257*0Sstevel@tonic-gate
1258*0Sstevel@tonic-gateThis may also be set to the special value C<none>, in which case no quote
1259*0Sstevel@tonic-gatemarks are added around CE<lt>> text (but the font is still changed for troff
1260*0Sstevel@tonic-gateoutput).
1261*0Sstevel@tonic-gate
1262*0Sstevel@tonic-gate=item release
1263*0Sstevel@tonic-gate
1264*0Sstevel@tonic-gateSet the centered footer.  By default, this is the version of Perl you run
1265*0Sstevel@tonic-gatePod::Man under.  Note that some system an macro sets assume that the
1266*0Sstevel@tonic-gatecentered footer will be a modification date and will prepend something like
1267*0Sstevel@tonic-gate"Last modified: "; if this is the case, you may want to set C<release> to
1268*0Sstevel@tonic-gatethe last modified date and C<date> to the version number.
1269*0Sstevel@tonic-gate
1270*0Sstevel@tonic-gate=item section
1271*0Sstevel@tonic-gate
1272*0Sstevel@tonic-gateSet the section for the C<.TH> macro.  The standard section numbering
1273*0Sstevel@tonic-gateconvention is to use 1 for user commands, 2 for system calls, 3 for
1274*0Sstevel@tonic-gatefunctions, 4 for devices, 5 for file formats, 6 for games, 7 for
1275*0Sstevel@tonic-gatemiscellaneous information, and 8 for administrator commands.  There is a lot
1276*0Sstevel@tonic-gateof variation here, however; some systems (like Solaris) use 4 for file
1277*0Sstevel@tonic-gateformats, 5 for miscellaneous information, and 7 for devices.  Still others
1278*0Sstevel@tonic-gateuse 1m instead of 8, or some mix of both.  About the only section numbers
1279*0Sstevel@tonic-gatethat are reliably consistent are 1, 2, and 3.
1280*0Sstevel@tonic-gate
1281*0Sstevel@tonic-gateBy default, section 1 will be used unless the file ends in .pm in which case
1282*0Sstevel@tonic-gatesection 3 will be selected.
1283*0Sstevel@tonic-gate
1284*0Sstevel@tonic-gate=back
1285*0Sstevel@tonic-gate
1286*0Sstevel@tonic-gateThe standard Pod::Parser method parse_from_filehandle() takes up to two
1287*0Sstevel@tonic-gatearguments, the first being the file handle to read POD from and the second
1288*0Sstevel@tonic-gatebeing the file handle to write the formatted output to.  The first defaults
1289*0Sstevel@tonic-gateto STDIN if not given, and the second defaults to STDOUT.  The method
1290*0Sstevel@tonic-gateparse_from_file() is almost identical, except that its two arguments are the
1291*0Sstevel@tonic-gateinput and output disk files instead.  See L<Pod::Parser> for the specific
1292*0Sstevel@tonic-gatedetails.
1293*0Sstevel@tonic-gate
1294*0Sstevel@tonic-gate=head1 DIAGNOSTICS
1295*0Sstevel@tonic-gate
1296*0Sstevel@tonic-gate=over 4
1297*0Sstevel@tonic-gate
1298*0Sstevel@tonic-gate=item roff font should be 1 or 2 chars, not "%s"
1299*0Sstevel@tonic-gate
1300*0Sstevel@tonic-gate(F) You specified a *roff font (using C<fixed>, C<fixedbold>, etc.) that
1301*0Sstevel@tonic-gatewasn't either one or two characters.  Pod::Man doesn't support *roff fonts
1302*0Sstevel@tonic-gatelonger than two characters, although some *roff extensions do (the canonical
1303*0Sstevel@tonic-gateversions of B<nroff> and B<troff> don't either).
1304*0Sstevel@tonic-gate
1305*0Sstevel@tonic-gate=item Invalid link %s
1306*0Sstevel@tonic-gate
1307*0Sstevel@tonic-gate(W) The POD source contained a C<LE<lt>E<gt>> formatting code that
1308*0Sstevel@tonic-gatePod::Man was unable to parse.  You should never see this error message; it
1309*0Sstevel@tonic-gateprobably indicates a bug in Pod::Man.
1310*0Sstevel@tonic-gate
1311*0Sstevel@tonic-gate=item Invalid quote specification "%s"
1312*0Sstevel@tonic-gate
1313*0Sstevel@tonic-gate(F) The quote specification given (the quotes option to the constructor) was
1314*0Sstevel@tonic-gateinvalid.  A quote specification must be one, two, or four characters long.
1315*0Sstevel@tonic-gate
1316*0Sstevel@tonic-gate=item %s:%d: Unknown command paragraph "%s".
1317*0Sstevel@tonic-gate
1318*0Sstevel@tonic-gate(W) The POD source contained a non-standard command paragraph (something of
1319*0Sstevel@tonic-gatethe form C<=command args>) that Pod::Man didn't know about.  It was ignored.
1320*0Sstevel@tonic-gate
1321*0Sstevel@tonic-gate=item %s:%d: Unknown escape EE<lt>%sE<gt>
1322*0Sstevel@tonic-gate
1323*0Sstevel@tonic-gate(W) The POD source contained an C<EE<lt>E<gt>> escape that Pod::Man didn't
1324*0Sstevel@tonic-gateknow about.  C<EE<lt>%sE<gt>> was printed verbatim in the output.
1325*0Sstevel@tonic-gate
1326*0Sstevel@tonic-gate=item %s:%d: Unknown formatting code %s
1327*0Sstevel@tonic-gate
1328*0Sstevel@tonic-gate(W) The POD source contained a non-standard formatting code (something of
1329*0Sstevel@tonic-gatethe form C<XE<lt>E<gt>>) that Pod::Man didn't know about.  It was ignored.
1330*0Sstevel@tonic-gate
1331*0Sstevel@tonic-gate=item %s:%d: Unmatched =back
1332*0Sstevel@tonic-gate
1333*0Sstevel@tonic-gate(W) Pod::Man encountered a C<=back> command that didn't correspond to an
1334*0Sstevel@tonic-gateC<=over> command.
1335*0Sstevel@tonic-gate
1336*0Sstevel@tonic-gate=back
1337*0Sstevel@tonic-gate
1338*0Sstevel@tonic-gate=head1 BUGS
1339*0Sstevel@tonic-gate
1340*0Sstevel@tonic-gateEight-bit input data isn't handled at all well at present.  The correct
1341*0Sstevel@tonic-gateapproach would be to map EE<lt>E<gt> escapes to the appropriate UTF-8
1342*0Sstevel@tonic-gatecharacters and then do a translation pass on the output according to the
1343*0Sstevel@tonic-gateuser-specified output character set.  Unfortunately, we can't send eight-bit
1344*0Sstevel@tonic-gatedata directly to the output unless the user says this is okay, since some
1345*0Sstevel@tonic-gatevendor *roff implementations can't handle eight-bit data.  If the *roff
1346*0Sstevel@tonic-gateimplementation can, however, that's far superior to the current hacked
1347*0Sstevel@tonic-gatecharacters that only work under troff.
1348*0Sstevel@tonic-gate
1349*0Sstevel@tonic-gateThere is currently no way to turn off the guesswork that tries to format
1350*0Sstevel@tonic-gateunmarked text appropriately, and sometimes it isn't wanted (particularly
1351*0Sstevel@tonic-gatewhen using POD to document something other than Perl).
1352*0Sstevel@tonic-gate
1353*0Sstevel@tonic-gateThe NAME section should be recognized specially and index entries emitted
1354*0Sstevel@tonic-gatefor everything in that section.  This would have to be deferred until the
1355*0Sstevel@tonic-gatenext section, since extraneous things in NAME tends to confuse various man
1356*0Sstevel@tonic-gatepage processors.
1357*0Sstevel@tonic-gate
1358*0Sstevel@tonic-gatePod::Man doesn't handle font names longer than two characters.  Neither do
1359*0Sstevel@tonic-gatemost B<troff> implementations, but GNU troff does as an extension.  It would
1360*0Sstevel@tonic-gatebe nice to support as an option for those who want to use it.
1361*0Sstevel@tonic-gate
1362*0Sstevel@tonic-gateThe preamble added to each output file is rather verbose, and most of it is
1363*0Sstevel@tonic-gateonly necessary in the presence of EE<lt>E<gt> escapes for non-ASCII
1364*0Sstevel@tonic-gatecharacters.  It would ideally be nice if all of those definitions were only
1365*0Sstevel@tonic-gateoutput if needed, perhaps on the fly as the characters are used.
1366*0Sstevel@tonic-gate
1367*0Sstevel@tonic-gatePod::Man is excessively slow.
1368*0Sstevel@tonic-gate
1369*0Sstevel@tonic-gate=head1 CAVEATS
1370*0Sstevel@tonic-gate
1371*0Sstevel@tonic-gateThe handling of hyphens and em dashes is somewhat fragile, and one may get
1372*0Sstevel@tonic-gatethe wrong one under some circumstances.  This should only matter for
1373*0Sstevel@tonic-gateB<troff> output.
1374*0Sstevel@tonic-gate
1375*0Sstevel@tonic-gateWhen and whether to use small caps is somewhat tricky, and Pod::Man doesn't
1376*0Sstevel@tonic-gatenecessarily get it right.
1377*0Sstevel@tonic-gate
1378*0Sstevel@tonic-gate=head1 SEE ALSO
1379*0Sstevel@tonic-gate
1380*0Sstevel@tonic-gateL<Pod::Parser>, L<perlpod(1)>, L<pod2man(1)>, L<nroff(1)>, L<troff(1)>,
1381*0Sstevel@tonic-gateL<man(1)>, L<man(7)>
1382*0Sstevel@tonic-gate
1383*0Sstevel@tonic-gateOssanna, Joseph F., and Brian W. Kernighan.  "Troff User's Manual,"
1384*0Sstevel@tonic-gateComputing Science Technical Report No. 54, AT&T Bell Laboratories.  This is
1385*0Sstevel@tonic-gatethe best documentation of standard B<nroff> and B<troff>.  At the time of
1386*0Sstevel@tonic-gatethis writing, it's available at
1387*0Sstevel@tonic-gateL<http://www.cs.bell-labs.com/cm/cs/cstr.html>.
1388*0Sstevel@tonic-gate
1389*0Sstevel@tonic-gateThe man page documenting the man macro set may be L<man(5)> instead of
1390*0Sstevel@tonic-gateL<man(7)> on your system.  Also, please see L<pod2man(1)> for extensive
1391*0Sstevel@tonic-gatedocumentation on writing manual pages if you've not done it before and
1392*0Sstevel@tonic-gatearen't familiar with the conventions.
1393*0Sstevel@tonic-gate
1394*0Sstevel@tonic-gateThe current version of this module is always available from its web site at
1395*0Sstevel@tonic-gateL<http://www.eyrie.org/~eagle/software/podlators/>.  It is also part of the
1396*0Sstevel@tonic-gatePerl core distribution as of 5.6.0.
1397*0Sstevel@tonic-gate
1398*0Sstevel@tonic-gate=head1 AUTHOR
1399*0Sstevel@tonic-gate
1400*0Sstevel@tonic-gateRuss Allbery <rra@stanford.edu>, based I<very> heavily on the original
1401*0Sstevel@tonic-gateB<pod2man> by Tom Christiansen <tchrist@mox.perl.com>.
1402*0Sstevel@tonic-gate
1403*0Sstevel@tonic-gate=head1 COPYRIGHT AND LICENSE
1404*0Sstevel@tonic-gate
1405*0Sstevel@tonic-gateCopyright 1999, 2000, 2001, 2002, 2003 by Russ Allbery <rra@stanford.edu>.
1406*0Sstevel@tonic-gate
1407*0Sstevel@tonic-gateThis program is free software; you may redistribute it and/or modify it
1408*0Sstevel@tonic-gateunder the same terms as Perl itself.
1409*0Sstevel@tonic-gate
1410*0Sstevel@tonic-gate=cut
1411