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