pod2man.pl 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. : #!/usr/bin/perl-5.005
  2. eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
  3. if $running_under_some_shell;
  4. $DEF_PM_SECTION = '3pm' || '3';
  5. =head1 NAME
  6. pod2man - translate embedded Perl pod directives into man pages
  7. =head1 SYNOPSIS
  8. B<pod2man>
  9. [ B<--section=>I<manext> ]
  10. [ B<--release=>I<relpatch> ]
  11. [ B<--center=>I<string> ]
  12. [ B<--date=>I<string> ]
  13. [ B<--fixed=>I<font> ]
  14. [ B<--official> ]
  15. [ B<--lax> ]
  16. I<inputfile>
  17. =head1 DESCRIPTION
  18. B<pod2man> converts its input file containing embedded pod directives (see
  19. L<perlpod>) into nroff source suitable for viewing with nroff(1) or
  20. troff(1) using the man(7) macro set.
  21. Besides the obvious pod conversions, B<pod2man> also takes care of
  22. func(), func(n), and simple variable references like $foo or @bar so
  23. you don't have to use code escapes for them; complex expressions like
  24. C<$fred{'stuff'}> will still need to be escaped, though. Other nagging
  25. little roffish things that it catches include translating the minus in
  26. something like foo-bar, making a long dash--like this--into a real em
  27. dash, fixing up "paired quotes", putting a little space after the
  28. parens in something like func(), making C++ and PI look right, making
  29. double underbars have a little tiny space between them, making ALLCAPS
  30. a teeny bit smaller in troff(1), and escaping backslashes so you don't
  31. have to.
  32. =head1 OPTIONS
  33. =over 8
  34. =item center
  35. Set the centered header to a specific string. The default is
  36. "User Contributed Perl Documentation", unless the C<--official> flag is
  37. given, in which case the default is "Perl Programmers Reference Guide".
  38. =item date
  39. Set the left-hand footer string to this value. By default,
  40. the modification date of the input file will be used.
  41. =item fixed
  42. The fixed font to use for code refs. Defaults to CW.
  43. =item official
  44. Set the default header to indicate that this page is of
  45. the standard release in case C<--center> is not given.
  46. =item release
  47. Set the centered footer. By default, this is the current
  48. perl release.
  49. =item section
  50. Set the section for the C<.TH> macro. The standard conventions on
  51. sections are to use 1 for user commands, 2 for system calls, 3 for
  52. functions, 4 for devices, 5 for file formats, 6 for games, 7 for
  53. miscellaneous information, and 8 for administrator commands. This works
  54. best if you put your Perl man pages in a separate tree, like
  55. F</usr/local/perl/man/>. By default, section 1 will be used
  56. unless the file ends in F<.pm> in which case section 3 will be selected.
  57. =item lax
  58. Don't complain when required sections aren't present.
  59. =back
  60. =head1 Anatomy of a Proper Man Page
  61. For those not sure of the proper layout of a man page, here's
  62. an example of the skeleton of a proper man page. Head of the
  63. major headers should be setout as a C<=head1> directive, and
  64. are historically written in the rather startling ALL UPPER CASE
  65. format, although this is not mandatory.
  66. Minor headers may be included using C<=head2>, and are
  67. typically in mixed case.
  68. =over 10
  69. =item NAME
  70. Mandatory section; should be a comma-separated list of programs or
  71. functions documented by this podpage, such as:
  72. foo, bar - programs to do something
  73. =item SYNOPSIS
  74. A short usage summary for programs and functions, which
  75. may someday be deemed mandatory.
  76. =item DESCRIPTION
  77. Long drawn out discussion of the program. It's a good idea to break this
  78. up into subsections using the C<=head2> directives, like
  79. =head2 A Sample Subection
  80. =head2 Yet Another Sample Subection
  81. =item OPTIONS
  82. Some people make this separate from the description.
  83. =item RETURN VALUE
  84. What the program or function returns if successful.
  85. =item ERRORS
  86. Exceptions, return codes, exit stati, and errno settings.
  87. =item EXAMPLES
  88. Give some example uses of the program.
  89. =item ENVIRONMENT
  90. Envariables this program might care about.
  91. =item FILES
  92. All files used by the program. You should probably use the FE<lt>E<gt>
  93. for these.
  94. =item SEE ALSO
  95. Other man pages to check out, like man(1), man(7), makewhatis(8), or catman(8).
  96. =item NOTES
  97. Miscellaneous commentary.
  98. =item CAVEATS
  99. Things to take special care with; sometimes called WARNINGS.
  100. =item DIAGNOSTICS
  101. All possible messages the program can print out--and
  102. what they mean.
  103. =item BUGS
  104. Things that are broken or just don't work quite right.
  105. =item RESTRICTIONS
  106. Bugs you don't plan to fix :-)
  107. =item AUTHOR
  108. Who wrote it (or AUTHORS if multiple).
  109. =item HISTORY
  110. Programs derived from other sources sometimes have this, or
  111. you might keep a modification log here.
  112. =back
  113. =head1 EXAMPLES
  114. pod2man program > program.1
  115. pod2man some_module.pm > /usr/perl/man/man3/some_module.3
  116. pod2man --section=7 note.pod > note.7
  117. =head1 DIAGNOSTICS
  118. The following diagnostics are generated by B<pod2man>. Items
  119. marked "(W)" are non-fatal, whereas the "(F)" errors will cause
  120. B<pod2man> to immediately exit with a non-zero status.
  121. =over 4
  122. =item bad option in paragraph %d of %s: ``%s'' should be [%s]<%s>
  123. (W) If you start include an option, you should set it off
  124. as bold, italic, or code.
  125. =item can't open %s: %s
  126. (F) The input file wasn't available for the given reason.
  127. =item Improper man page - no dash in NAME header in paragraph %d of %s
  128. (W) The NAME header did not have an isolated dash in it. This is
  129. considered important.
  130. =item Invalid man page - no NAME line in %s
  131. (F) You did not include a NAME header, which is essential.
  132. =item roff font should be 1 or 2 chars, not `%s' (F)
  133. (F) The font specified with the C<--fixed> option was not
  134. a one- or two-digit roff font.
  135. =item %s is missing required section: %s
  136. (W) Required sections include NAME, DESCRIPTION, and if you're
  137. using a section starting with a 3, also a SYNOPSIS. Actually,
  138. not having a NAME is a fatal.
  139. =item Unknown escape: %s in %s
  140. (W) An unknown HTML entity (probably for an 8-bit character) was given via
  141. a C<EE<lt>E<gt>> directive. Besides amp, lt, gt, and quot, recognized
  142. entities are Aacute, aacute, Acirc, acirc, AElig, aelig, Agrave, agrave,
  143. Aring, aring, Atilde, atilde, Auml, auml, Ccedil, ccedil, Eacute, eacute,
  144. Ecirc, ecirc, Egrave, egrave, ETH, eth, Euml, euml, Iacute, iacute, Icirc,
  145. icirc, Igrave, igrave, Iuml, iuml, Ntilde, ntilde, Oacute, oacute, Ocirc,
  146. ocirc, Ograve, ograve, Oslash, oslash, Otilde, otilde, Ouml, ouml, szlig,
  147. THORN, thorn, Uacute, uacute, Ucirc, ucirc, Ugrave, ugrave, Uuml, uuml,
  148. Yacute, yacute, and yuml.
  149. =item Unmatched =back
  150. (W) You have a C<=back> without a corresponding C<=over>.
  151. =item Unrecognized pod directive: %s
  152. (W) You specified a pod directive that isn't in the known list of
  153. C<=head1>, C<=head2>, C<=item>, C<=over>, C<=back>, or C<=cut>.
  154. =back
  155. =head1 NOTES
  156. If you would like to print out a lot of man page continuously, you
  157. probably want to set the C and D registers to set contiguous page
  158. numbering and even/odd paging, at least on some versions of man(7).
  159. Settting the F register will get you some additional experimental
  160. indexing:
  161. troff -man -rC1 -rD1 -rF1 perl.1 perldata.1 perlsyn.1 ...
  162. The indexing merely outputs messages via C<.tm> for each
  163. major page, section, subsection, item, and any C<XE<lt>E<gt>>
  164. directives.
  165. =head1 RESTRICTIONS
  166. None at this time.
  167. =head1 BUGS
  168. The =over and =back directives don't really work right. They
  169. take absolute positions instead of offsets, don't nest well, and
  170. making people count is suboptimal in any event.
  171. =head1 AUTHORS
  172. Original prototype by Larry Wall, but so massively hacked over by
  173. Tom Christiansen such that Larry probably doesn't recognize it anymore.
  174. =cut
  175. $/ = "";
  176. $cutting = 1;
  177. @Indices = ();
  178. # We try first to get the version number from a local binary, in case we're
  179. # running an installed version of Perl to produce documentation from an
  180. # uninstalled newer version's pod files.
  181. if ($^O ne 'plan9' and $^O ne 'dos' and $^O ne 'os2' and $^O ne 'MSWin32') {
  182. my $perl = (-x './perl' && -f './perl' ) ?
  183. './perl' :
  184. ((-x '../perl' && -f '../perl') ?
  185. '../perl' :
  186. '');
  187. ($version,$patch) = `$perl -e 'print $]'` =~ /^(\d\.\d{3})(\d{2})?/ if $perl;
  188. }
  189. # No luck; we'll just go with the running Perl's version
  190. ($version,$patch) = $] =~ /^(.{5})(\d{2})?/ unless $version;
  191. $DEF_RELEASE = "perl $version";
  192. $DEF_RELEASE .= ", patch $patch" if $patch;
  193. sub makedate {
  194. my $secs = shift;
  195. my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($secs);
  196. my $mname = (qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec})[$mon];
  197. $year += 1900;
  198. return "$mday/$mname/$year";
  199. }
  200. use Getopt::Long;
  201. $DEF_SECTION = 1;
  202. $DEF_CENTER = "User Contributed Perl Documentation";
  203. $STD_CENTER = "Perl Programmers Reference Guide";
  204. $DEF_FIXED = 'CW';
  205. $DEF_LAX = 0;
  206. sub usage {
  207. warn "$0: @_\n" if @_;
  208. die <<EOF;
  209. usage: $0 [options] podpage
  210. Options are:
  211. --section=manext (default "$DEF_SECTION")
  212. --release=relpatch (default "$DEF_RELEASE")
  213. --center=string (default "$DEF_CENTER")
  214. --date=string (default "$DEF_DATE")
  215. --fixed=font (default "$DEF_FIXED")
  216. --official (default NOT)
  217. --lax (default NOT)
  218. EOF
  219. }
  220. $uok = GetOptions( qw(
  221. section=s
  222. release=s
  223. center=s
  224. date=s
  225. fixed=s
  226. official
  227. lax
  228. help));
  229. $DEF_DATE = makedate((stat($ARGV[0]))[9] || time());
  230. usage("Usage error!") unless $uok;
  231. usage() if $opt_help;
  232. usage("Need one and only one podpage argument") unless @ARGV == 1;
  233. $section = $opt_section || ($ARGV[0] =~ /\.pm$/
  234. ? $DEF_PM_SECTION : $DEF_SECTION);
  235. $RP = $opt_release || $DEF_RELEASE;
  236. $center = $opt_center || ($opt_official ? $STD_CENTER : $DEF_CENTER);
  237. $lax = $opt_lax || $DEF_LAX;
  238. $CFont = $opt_fixed || $DEF_FIXED;
  239. if (length($CFont) == 2) {
  240. $CFont_embed = "\\f($CFont";
  241. }
  242. elsif (length($CFont) == 1) {
  243. $CFont_embed = "\\f$CFont";
  244. }
  245. else {
  246. die "roff font should be 1 or 2 chars, not `$CFont_embed'";
  247. }
  248. $date = $opt_date || $DEF_DATE;
  249. for (qw{NAME DESCRIPTION}) {
  250. # for (qw{NAME DESCRIPTION AUTHOR}) {
  251. $wanna_see{$_}++;
  252. }
  253. $wanna_see{SYNOPSIS}++ if $section =~ /^3/;
  254. $name = @ARGV ? $ARGV[0] : "<STDIN>";
  255. $Filename = $name;
  256. if ($section =~ /^1/) {
  257. require File::Basename;
  258. $name = uc File::Basename::basename($name);
  259. }
  260. $name =~ s/\.(pod|p[lm])$//i;
  261. # Lose everything up to the first of
  262. # */lib/*perl* standard or site_perl module
  263. # */*perl*/lib from -D prefix=/opt/perl
  264. # */*perl*/ random module hierarchy
  265. # which works.
  266. $name =~ s-//+-/-g;
  267. if ($name =~ s-^.*?/lib/[^/]*perl[^/]*/--i
  268. or $name =~ s-^.*?/[^/]*perl[^/]*/lib/--i
  269. or $name =~ s-^.*?/[^/]*perl[^/]*/--i) {
  270. # Lose ^site(_perl)?/.
  271. $name =~ s-^site(_perl)?/--;
  272. # Lose ^arch/. (XXX should we use Config? Just for archname?)
  273. $name =~ s~^(.*-$^O|$^O-.*)/~~o;
  274. # Lose ^version/.
  275. $name =~ s-^\d+\.\d+/--;
  276. }
  277. # Translate Getopt/Long to Getopt::Long, etc.
  278. $name =~ s(/)(::)g;
  279. if ($name ne 'something') {
  280. FCHECK: {
  281. open(F, "< $ARGV[0]") || die "can't open $ARGV[0]: $!";
  282. while (<F>) {
  283. next unless /^=\b/;
  284. if (/^=head1\s+NAME\s*$/) { # an /m would forgive mistakes
  285. $_ = <F>;
  286. unless (/\s*-+\s+/) {
  287. $oops++;
  288. warn "$0: Improper man page - no dash in NAME header in paragraph $. of $ARGV[0]\n"
  289. } else {
  290. my @n = split /\s+-+\s+/;
  291. if (@n != 2) {
  292. $oops++;
  293. warn "$0: Improper man page - malformed NAME header in paragraph $. of $ARGV[0]\n"
  294. }
  295. else {
  296. $n[0] =~ s/\n/ /g;
  297. $n[1] =~ s/\n/ /g;
  298. %namedesc = @n;
  299. }
  300. }
  301. last FCHECK;
  302. }
  303. next if /^=cut\b/; # DB_File and Net::Ping have =cut before NAME
  304. next if /^=pod\b/; # It is OK to have =pod before NAME
  305. next if /^=for\s+comment\b/; # It is OK to have =for comment before NAME
  306. die "$0: Invalid man page - 1st pod line is not NAME in $ARGV[0]\n" unless $lax;
  307. }
  308. die "$0: Invalid man page - no documentation in $ARGV[0]\n" unless $lax;
  309. }
  310. close F;
  311. }
  312. print <<"END";
  313. .rn '' }`
  314. ''' \$RCSfile\$\$Revision\$\$Date\$
  315. '''
  316. ''' \$Log\$
  317. '''
  318. .de Sh
  319. .br
  320. .if t .Sp
  321. .ne 5
  322. .PP
  323. \\fB\\\\\$1\\fR
  324. .PP
  325. ..
  326. .de Sp
  327. .if t .sp .5v
  328. .if n .sp
  329. ..
  330. .de Ip
  331. .br
  332. .ie \\\\n(.\$>=3 .ne \\\\\$3
  333. .el .ne 3
  334. .IP "\\\\\$1" \\\\\$2
  335. ..
  336. .de Vb
  337. .ft $CFont
  338. .nf
  339. .ne \\\\\$1
  340. ..
  341. .de Ve
  342. .ft R
  343. .fi
  344. ..
  345. '''
  346. '''
  347. ''' Set up \\*(-- to give an unbreakable dash;
  348. ''' string Tr holds user defined translation string.
  349. ''' Bell System Logo is used as a dummy character.
  350. '''
  351. .tr \\(*W-|\\(bv\\*(Tr
  352. .ie n \\{\\
  353. .ds -- \\(*W-
  354. .ds PI pi
  355. .if (\\n(.H=4u)&(1m=24u) .ds -- \\(*W\\h'-12u'\\(*W\\h'-12u'-\\" diablo 10 pitch
  356. .if (\\n(.H=4u)&(1m=20u) .ds -- \\(*W\\h'-12u'\\(*W\\h'-8u'-\\" diablo 12 pitch
  357. .ds L" ""
  358. .ds R" ""
  359. ''' \\*(M", \\*(S", \\*(N" and \\*(T" are the equivalent of
  360. ''' \\*(L" and \\*(R", except that they are used on ".xx" lines,
  361. ''' such as .IP and .SH, which do another additional levels of
  362. ''' double-quote interpretation
  363. .ds M" """
  364. .ds S" """
  365. .ds N" """""
  366. .ds T" """""
  367. .ds L' '
  368. .ds R' '
  369. .ds M' '
  370. .ds S' '
  371. .ds N' '
  372. .ds T' '
  373. 'br\\}
  374. .el\\{\\
  375. .ds -- \\(em\\|
  376. .tr \\*(Tr
  377. .ds L" ``
  378. .ds R" ''
  379. .ds M" ``
  380. .ds S" ''
  381. .ds N" ``
  382. .ds T" ''
  383. .ds L' `
  384. .ds R' '
  385. .ds M' `
  386. .ds S' '
  387. .ds N' `
  388. .ds T' '
  389. .ds PI \\(*p
  390. 'br\\}
  391. END
  392. print <<'END';
  393. .\" If the F register is turned on, we'll generate
  394. .\" index entries out stderr for the following things:
  395. .\" TH Title
  396. .\" SH Header
  397. .\" Sh Subsection
  398. .\" Ip Item
  399. .\" X<> Xref (embedded
  400. .\" Of course, you have to process the output yourself
  401. .\" in some meaninful fashion.
  402. .if \nF \{
  403. .de IX
  404. .tm Index:\\$1\t\\n%\t"\\$2"
  405. ..
  406. .nr % 0
  407. .rr F
  408. .\}
  409. END
  410. print <<"END";
  411. .TH $name $section "$RP" "$date" "$center"
  412. .UC
  413. END
  414. push(@Indices, qq{.IX Title "$name $section"});
  415. while (($name, $desc) = each %namedesc) {
  416. for ($name, $desc) { s/^\s+//; s/\s+$//; }
  417. push(@Indices, qq(.IX Name "$name - $desc"\n));
  418. }
  419. print <<'END';
  420. .if n .hy 0
  421. .if n .na
  422. .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
  423. .de CQ \" put $1 in typewriter font
  424. END
  425. print ".ft $CFont\n";
  426. print <<'END';
  427. 'if n "\c
  428. 'if t \\&\\$1\c
  429. 'if n \\&\\$1\c
  430. 'if n \&"
  431. \\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7
  432. '.ft R
  433. ..
  434. .\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2
  435. . \" AM - accent mark definitions
  436. .bd B 3
  437. . \" fudge factors for nroff and troff
  438. .if n \{\
  439. . ds #H 0
  440. . ds #V .8m
  441. . ds #F .3m
  442. . ds #[ \f1
  443. . ds #] \fP
  444. .\}
  445. .if t \{\
  446. . ds #H ((1u-(\\\\n(.fu%2u))*.13m)
  447. . ds #V .6m
  448. . ds #F 0
  449. . ds #[ \&
  450. . ds #] \&
  451. .\}
  452. . \" simple accents for nroff and troff
  453. .if n \{\
  454. . ds ' \&
  455. . ds ` \&
  456. . ds ^ \&
  457. . ds , \&
  458. . ds ~ ~
  459. . ds ? ?
  460. . ds ! !
  461. . ds /
  462. . ds q
  463. .\}
  464. .if t \{\
  465. . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
  466. . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
  467. . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
  468. . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
  469. . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
  470. . ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10'
  471. . ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m'
  472. . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
  473. . ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10'
  474. .\}
  475. . \" troff and (daisy-wheel) nroff accents
  476. .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
  477. .ds 8 \h'\*(#H'\(*b\h'-\*(#H'
  478. .ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#]
  479. .ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u'
  480. .ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u'
  481. .ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#]
  482. .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
  483. .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
  484. .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
  485. .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
  486. .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
  487. .ds ae a\h'-(\w'a'u*4/10)'e
  488. .ds Ae A\h'-(\w'A'u*4/10)'E
  489. .ds oe o\h'-(\w'o'u*4/10)'e
  490. .ds Oe O\h'-(\w'O'u*4/10)'E
  491. . \" corrections for vroff
  492. .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
  493. .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
  494. . \" for low resolution devices (crt and lpr)
  495. .if \n(.H>23 .if \n(.V>19 \
  496. \{\
  497. . ds : e
  498. . ds 8 ss
  499. . ds v \h'-1'\o'\(aa\(ga'
  500. . ds _ \h'-1'^
  501. . ds . \h'-1'.
  502. . ds 3 3
  503. . ds o a
  504. . ds d- d\h'-1'\(ga
  505. . ds D- D\h'-1'\(hy
  506. . ds th \o'bp'
  507. . ds Th \o'LP'
  508. . ds ae ae
  509. . ds Ae AE
  510. . ds oe oe
  511. . ds Oe OE
  512. .\}
  513. .rm #[ #] #H #V #F C
  514. END
  515. $indent = 0;
  516. $begun = "";
  517. # Unrolling [^A-Z>]|[A-Z](?!<) gives: // MRE pp 165.
  518. my $nonest = '(?:[^A-Z>]*(?:[A-Z](?!<)[^A-Z>]*)*)';
  519. while (<>) {
  520. if ($cutting) {
  521. next unless /^=/;
  522. $cutting = 0;
  523. }
  524. if ($begun) {
  525. if (/^=end\s+$begun/) {
  526. $begun = "";
  527. }
  528. elsif ($begun =~ /^(roff|man)$/) {
  529. print STDOUT $_;
  530. }
  531. next;
  532. }
  533. chomp;
  534. # Translate verbatim paragraph
  535. if (/^\s/) {
  536. @lines = split(/\n/);
  537. for (@lines) {
  538. 1 while s
  539. {^( [^\t]* ) \t ( \t* ) }
  540. { $1 . ' ' x (8 - (length($1)%8) + 8 * (length($2))) }ex;
  541. s/\\/\\e/g;
  542. s/\A/\\&/s;
  543. }
  544. $lines = @lines;
  545. makespace() unless $verbatim++;
  546. print ".Vb $lines\n";
  547. print join("\n", @lines), "\n";
  548. print ".Ve\n";
  549. $needspace = 0;
  550. next;
  551. }
  552. $verbatim = 0;
  553. if (/^=for\s+(\S+)\s*/s) {
  554. if ($1 eq "man" or $1 eq "roff") {
  555. print STDOUT $',"\n\n";
  556. } else {
  557. # ignore unknown for
  558. }
  559. next;
  560. }
  561. elsif (/^=begin\s+(\S+)\s*/s) {
  562. $begun = $1;
  563. if ($1 eq "man" or $1 eq "roff") {
  564. print STDOUT $'."\n\n";
  565. }
  566. next;
  567. }
  568. # check for things that'll hosed our noremap scheme; affects $_
  569. init_noremap();
  570. if (!/^=item/) {
  571. # trofficate backslashes; must do it before what happens below
  572. s/\\/noremap('\\e')/ge;
  573. # protect leading periods and quotes against *roff
  574. # mistaking them for directives
  575. s/^(?:[A-Z]<)?[.']/\\&$&/gm;
  576. # first hide the escapes in case we need to
  577. # intuit something and get it wrong due to fmting
  578. 1 while s/([A-Z]<$nonest>)/noremap($1)/ge;
  579. # func() is a reference to a perl function
  580. s{
  581. \b
  582. (
  583. [:\w]+ \(\)
  584. )
  585. } {I<$1>}gx;
  586. # func(n) is a reference to a perl function or a man page
  587. s{
  588. ([:\w]+)
  589. (
  590. \( [^\051]+ \)
  591. )
  592. } {I<$1>\\|$2}gx;
  593. # convert simple variable references
  594. s/(\s+)([\$\@%][\w:]+)(?!\()/${1}C<$2>/g;
  595. if (m{ (
  596. [\-\w]+
  597. \(
  598. [^\051]*?
  599. [\@\$,]
  600. [^\051]*?
  601. \)
  602. )
  603. }x && $` !~ /([LCI]<[^<>]*|-)$/ && !/^=\w/)
  604. {
  605. warn "$0: bad option in paragraph $. of $ARGV: ``$1'' should be [LCI]<$1>\n";
  606. $oops++;
  607. }
  608. while (/(-[a-zA-Z])\b/g && $` !~ /[\w\-]$/) {
  609. warn "$0: bad option in paragraph $. of $ARGV: ``$1'' should be [CB]<$1>\n";
  610. $oops++;
  611. }
  612. # put it back so we get the <> processed again;
  613. clear_noremap(0); # 0 means leave the E's
  614. } else {
  615. # trofficate backslashes
  616. s/\\/noremap('\\e')/ge;
  617. }
  618. # need to hide E<> first; they're processed in clear_noremap
  619. s/(E<[^<>]+>)/noremap($1)/ge;
  620. $maxnest = 10;
  621. while ($maxnest-- && /[A-Z]</) {
  622. # can't do C font here
  623. s/([BI])<($nonest)>/font($1) . $2 . font('R')/eg;
  624. # files and filelike refs in italics
  625. s/F<($nonest)>/I<$1>/g;
  626. # no break -- usually we want C<> for this
  627. s/S<($nonest)>/nobreak($1)/eg;
  628. # LREF: a la HREF L<show this text|man/section>
  629. s:L<([^|>]+)\|[^>]+>:$1:g;
  630. # LREF: a manpage(3f)
  631. s:L<([a-zA-Z][^\s\/]+)(\([^\)]+\))?>:the I<$1>$2 manpage:g;
  632. # LREF: an =item on another manpage
  633. s{
  634. L<
  635. ([^/]+)
  636. /
  637. (
  638. [:\w]+
  639. (\(\))?
  640. )
  641. >
  642. } {the C<$2> entry in the I<$1> manpage}gx;
  643. # LREF: an =item on this manpage
  644. s{
  645. ((?:
  646. L<
  647. /
  648. (
  649. [:\w]+
  650. (\(\))?
  651. )
  652. >
  653. (,?\s+(and\s+)?)?
  654. )+)
  655. } { internal_lrefs($1) }gex;
  656. # LREF: a =head2 (head1?), maybe on a manpage, maybe right here
  657. # the "func" can disambiguate
  658. s{
  659. L<
  660. (?:
  661. ([a-zA-Z]\S+?) /
  662. )?
  663. "?(.*?)"?
  664. >
  665. }{
  666. do {
  667. $1 # if no $1, assume it means on this page.
  668. ? "the section on I<$2> in the I<$1> manpage"
  669. : "the section on I<$2>"
  670. }
  671. }gesx; # s in case it goes over multiple lines, so . matches \n
  672. s/Z<>/\\&/g;
  673. # comes last because not subject to reprocessing
  674. s/C<($nonest)>/noremap("${CFont_embed}${1}\\fR")/eg;
  675. }
  676. if (s/^=//) {
  677. $needspace = 0; # Assume this.
  678. s/\n/ /g;
  679. ($Cmd, $_) = split(' ', $_, 2);
  680. $dotlevel = 1;
  681. if ($Cmd eq 'head1') {
  682. $dotlevel = 1;
  683. }
  684. elsif ($Cmd eq 'head2') {
  685. $dotlevel = 1;
  686. }
  687. elsif ($Cmd eq 'item') {
  688. $dotlevel = 2;
  689. }
  690. if (defined $_) {
  691. &escapes($dotlevel);
  692. s/"/""/g;
  693. }
  694. clear_noremap(1);
  695. if ($Cmd eq 'cut') {
  696. $cutting = 1;
  697. }
  698. elsif ($Cmd eq 'head1') {
  699. s/\s+$//;
  700. delete $wanna_see{$_} if exists $wanna_see{$_};
  701. print qq{.SH "$_"\n};
  702. push(@Indices, qq{.IX Header "$_"\n});
  703. }
  704. elsif ($Cmd eq 'head2') {
  705. print qq{.Sh "$_"\n};
  706. push(@Indices, qq{.IX Subsection "$_"\n});
  707. }
  708. elsif ($Cmd eq 'over') {
  709. push(@indent,$indent);
  710. $indent += ($_ + 0) || 5;
  711. }
  712. elsif ($Cmd eq 'back') {
  713. $indent = pop(@indent);
  714. warn "$0: Unmatched =back in paragraph $. of $ARGV\n" unless defined $indent;
  715. $needspace = 1;
  716. }
  717. elsif ($Cmd eq 'item') {
  718. s/^\*( |$)/\\(bu$1/g;
  719. # if you know how to get ":s please do
  720. s/\\\*\(L"([^"]+?)\\\*\(R"/'$1'/g;
  721. s/\\\*\(L"([^"]+?)""/'$1'/g;
  722. s/[^"]""([^"]+?)""[^"]/'$1'/g;
  723. # here do something about the $" in perlvar?
  724. print STDOUT qq{.Ip "$_" $indent\n};
  725. push(@Indices, qq{.IX Item "$_"\n});
  726. }
  727. elsif ($Cmd eq 'pod') {
  728. # this is just a comment
  729. }
  730. else {
  731. warn "$0: Unrecognized pod directive in paragraph $. of $ARGV: $Cmd\n";
  732. }
  733. }
  734. else {
  735. if ($needspace) {
  736. &makespace;
  737. }
  738. &escapes(0);
  739. clear_noremap(1);
  740. print $_, "\n";
  741. $needspace = 1;
  742. }
  743. }
  744. print <<"END";
  745. .rn }` ''
  746. END
  747. if (%wanna_see && !$lax) {
  748. @missing = keys %wanna_see;
  749. warn "$0: $Filename is missing required section"
  750. . (@missing > 1 && "s")
  751. . ": @missing\n";
  752. $oops++;
  753. }
  754. foreach (@Indices) { print "$_\n"; }
  755. exit;
  756. #exit ($oops != 0);
  757. #########################################################################
  758. sub nobreak {
  759. my $string = shift;
  760. $string =~ s/ /\\ /g;
  761. $string;
  762. }
  763. sub escapes {
  764. my $indot = shift;
  765. s/X<(.*?)>/mkindex($1)/ge;
  766. # translate the minus in foo-bar into foo\-bar for roff
  767. s/([^0-9a-z-])-([^-])/$1\\-$2/g;
  768. # make -- into the string version \*(-- (defined above)
  769. s/\b--\b/\\*(--/g;
  770. s/"--([^"])/"\\*(--$1/g; # should be a better way
  771. s/([^"])--"/$1\\*(--"/g;
  772. # fix up quotes; this is somewhat tricky
  773. my $dotmacroL = 'L';
  774. my $dotmacroR = 'R';
  775. if ( $indot == 1 ) {
  776. $dotmacroL = 'M';
  777. $dotmacroR = 'S';
  778. }
  779. elsif ( $indot >= 2 ) {
  780. $dotmacroL = 'N';
  781. $dotmacroR = 'T';
  782. }
  783. if (!/""/) {
  784. s/(^|\s)(['"])/noremap("$1\\*($dotmacroL$2")/ge;
  785. s/(['"])($|[\-\s,;\\!?.])/noremap("\\*($dotmacroR$1$2")/ge;
  786. }
  787. #s/(?!")(?:.)--(?!")(?:.)/\\*(--/g;
  788. #s/(?:(?!")(?:.)--(?:"))|(?:(?:")--(?!")(?:.))/\\*(--/g;
  789. # make sure that func() keeps a bit a space tween the parens
  790. ### s/\b\(\)/\\|()/g;
  791. ### s/\b\(\)/(\\|)/g;
  792. # make C++ into \*C+, which is a squinched version (defined above)
  793. s/\bC\+\+/\\*(C+/g;
  794. # make double underbars have a little tiny space between them
  795. s/__/_\\|_/g;
  796. # PI goes to \*(PI (defined above)
  797. s/\bPI\b/noremap('\\*(PI')/ge;
  798. # make all caps a teeny bit smaller, but don't muck with embedded code literals
  799. my $hidCFont = font('C');
  800. if ($Cmd !~ /^head1/) { # SH already makes smaller
  801. # /g isn't enough; 1 while or we'll be off
  802. # 1 while s{
  803. # (?!$hidCFont)(..|^.|^)
  804. # \b
  805. # (
  806. # [A-Z][\/A-Z+:\-\d_$.]+
  807. # )
  808. # (s?)
  809. # \b
  810. # } {$1\\s-1$2\\s0}gmox;
  811. 1 while s{
  812. (?!$hidCFont)(..|^.|^)
  813. (
  814. \b[A-Z]{2,}[\/A-Z+:\-\d_\$]*\b
  815. )
  816. } {
  817. $1 . noremap( '\\s-1' . $2 . '\\s0' )
  818. }egmox;
  819. }
  820. }
  821. # make troff just be normal, but make small nroff get quoted
  822. # decided to just put the quotes in the text; sigh;
  823. sub ccvt {
  824. local($_,$prev) = @_;
  825. noremap(qq{.CQ "$_" \n\\&});
  826. }
  827. sub makespace {
  828. if ($indent) {
  829. print ".Sp\n";
  830. }
  831. else {
  832. print ".PP\n";
  833. }
  834. }
  835. sub mkindex {
  836. my ($entry) = @_;
  837. my @entries = split m:\s*/\s*:, $entry;
  838. push @Indices, ".IX Xref " . join ' ', map {qq("$_")} @entries;
  839. return '';
  840. }
  841. sub font {
  842. local($font) = shift;
  843. return '\\f' . noremap($font);
  844. }
  845. sub noremap {
  846. local($thing_to_hide) = shift;
  847. $thing_to_hide =~ tr/\000-\177/\200-\377/;
  848. return $thing_to_hide;
  849. }
  850. sub init_noremap {
  851. # escape high bit characters in input stream
  852. s/([\200-\377])/"E<".ord($1).">"/ge;
  853. }
  854. sub clear_noremap {
  855. my $ready_to_print = $_[0];
  856. tr/\200-\377/\000-\177/;
  857. # trofficate backslashes
  858. # s/(?!\\e)(?:..|^.|^)\\/\\e/g;
  859. # now for the E<>s, which have been hidden until now
  860. # otherwise the interative \w<> processing would have
  861. # been hosed by the E<gt>
  862. s {
  863. E<
  864. (
  865. ( \d + )
  866. | ( [A-Za-z]+ )
  867. )
  868. >
  869. } {
  870. do {
  871. defined $2
  872. ? chr($2)
  873. :
  874. exists $HTML_Escapes{$3}
  875. ? do { $HTML_Escapes{$3} }
  876. : do {
  877. warn "$0: Unknown escape in paragraph $. of $ARGV: ``$&''\n";
  878. "E<$1>";
  879. }
  880. }
  881. }egx if $ready_to_print;
  882. }
  883. sub internal_lrefs {
  884. local($_) = shift;
  885. local $trailing_and = s/and\s+$// ? "and " : "";
  886. s{L</([^>]+)>}{$1}g;
  887. my(@items) = split( /(?:,?\s+(?:and\s+)?)/ );
  888. my $retstr = "the ";
  889. my $i;
  890. for ($i = 0; $i <= $#items; $i++) {
  891. $retstr .= "C<$items[$i]>";
  892. $retstr .= ", " if @items > 2 && $i != $#items;
  893. $retstr .= " and " if $i+2 == @items;
  894. }
  895. $retstr .= " entr" . ( @items > 1 ? "ies" : "y" )
  896. . " elsewhere in this document";
  897. # terminal space to avoid words running together (pattern used
  898. # strips terminal spaces)
  899. $retstr .= " " if length $trailing_and;
  900. $retstr .= $trailing_and;
  901. return $retstr;
  902. }
  903. BEGIN {
  904. %HTML_Escapes = (
  905. 'amp' => '&', # ampersand
  906. 'lt' => '<', # left chevron, less-than
  907. 'gt' => '>', # right chevron, greater-than
  908. 'quot' => '"', # double quote
  909. "Aacute" => "A\\*'", # capital A, acute accent
  910. "aacute" => "a\\*'", # small a, acute accent
  911. "Acirc" => "A\\*^", # capital A, circumflex accent
  912. "acirc" => "a\\*^", # small a, circumflex accent
  913. "AElig" => '\*(AE', # capital AE diphthong (ligature)
  914. "aelig" => '\*(ae', # small ae diphthong (ligature)
  915. "Agrave" => "A\\*`", # capital A, grave accent
  916. "agrave" => "A\\*`", # small a, grave accent
  917. "Aring" => 'A\\*o', # capital A, ring
  918. "aring" => 'a\\*o', # small a, ring
  919. "Atilde" => 'A\\*~', # capital A, tilde
  920. "atilde" => 'a\\*~', # small a, tilde
  921. "Auml" => 'A\\*:', # capital A, dieresis or umlaut mark
  922. "auml" => 'a\\*:', # small a, dieresis or umlaut mark
  923. "Ccedil" => 'C\\*,', # capital C, cedilla
  924. "ccedil" => 'c\\*,', # small c, cedilla
  925. "Eacute" => "E\\*'", # capital E, acute accent
  926. "eacute" => "e\\*'", # small e, acute accent
  927. "Ecirc" => "E\\*^", # capital E, circumflex accent
  928. "ecirc" => "e\\*^", # small e, circumflex accent
  929. "Egrave" => "E\\*`", # capital E, grave accent
  930. "egrave" => "e\\*`", # small e, grave accent
  931. "ETH" => '\\*(D-', # capital Eth, Icelandic
  932. "eth" => '\\*(d-', # small eth, Icelandic
  933. "Euml" => "E\\*:", # capital E, dieresis or umlaut mark
  934. "euml" => "e\\*:", # small e, dieresis or umlaut mark
  935. "Iacute" => "I\\*'", # capital I, acute accent
  936. "iacute" => "i\\*'", # small i, acute accent
  937. "Icirc" => "I\\*^", # capital I, circumflex accent
  938. "icirc" => "i\\*^", # small i, circumflex accent
  939. "Igrave" => "I\\*`", # capital I, grave accent
  940. "igrave" => "i\\*`", # small i, grave accent
  941. "Iuml" => "I\\*:", # capital I, dieresis or umlaut mark
  942. "iuml" => "i\\*:", # small i, dieresis or umlaut mark
  943. "Ntilde" => 'N\*~', # capital N, tilde
  944. "ntilde" => 'n\*~', # small n, tilde
  945. "Oacute" => "O\\*'", # capital O, acute accent
  946. "oacute" => "o\\*'", # small o, acute accent
  947. "Ocirc" => "O\\*^", # capital O, circumflex accent
  948. "ocirc" => "o\\*^", # small o, circumflex accent
  949. "Ograve" => "O\\*`", # capital O, grave accent
  950. "ograve" => "o\\*`", # small o, grave accent
  951. "Oslash" => "O\\*/", # capital O, slash
  952. "oslash" => "o\\*/", # small o, slash
  953. "Otilde" => "O\\*~", # capital O, tilde
  954. "otilde" => "o\\*~", # small o, tilde
  955. "Ouml" => "O\\*:", # capital O, dieresis or umlaut mark
  956. "ouml" => "o\\*:", # small o, dieresis or umlaut mark
  957. "szlig" => '\*8', # small sharp s, German (sz ligature)
  958. "THORN" => '\\*(Th', # capital THORN, Icelandic
  959. "thorn" => '\\*(th',, # small thorn, Icelandic
  960. "Uacute" => "U\\*'", # capital U, acute accent
  961. "uacute" => "u\\*'", # small u, acute accent
  962. "Ucirc" => "U\\*^", # capital U, circumflex accent
  963. "ucirc" => "u\\*^", # small u, circumflex accent
  964. "Ugrave" => "U\\*`", # capital U, grave accent
  965. "ugrave" => "u\\*`", # small u, grave accent
  966. "Uuml" => "U\\*:", # capital U, dieresis or umlaut mark
  967. "uuml" => "u\\*:", # small u, dieresis or umlaut mark
  968. "Yacute" => "Y\\*'", # capital Y, acute accent
  969. "yacute" => "y\\*'", # small y, acute accent
  970. "yuml" => "y\\*:", # small y, dieresis or umlaut mark
  971. );
  972. }