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