159191Skris: #!/usr/bin/perl-5.005 259191Skris eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' 359191Skris if $running_under_some_shell; 459191Skris 559191Skris$DEF_PM_SECTION = '3pm' || '3'; 659191Skris 759191Skris=head1 NAME 859191Skris 959191Skrispod2man - translate embedded Perl pod directives into man pages 1059191Skris 1159191Skris=head1 SYNOPSIS 1259191Skris 1359191SkrisB<pod2man> 1459191Skris[ B<--section=>I<manext> ] 1559191Skris[ B<--release=>I<relpatch> ] 1659191Skris[ B<--center=>I<string> ] 1759191Skris[ B<--date=>I<string> ] 1859191Skris[ B<--fixed=>I<font> ] 1959191Skris[ B<--official> ] 2059191Skris[ B<--lax> ] 2159191SkrisI<inputfile> 2259191Skris 2359191Skris=head1 DESCRIPTION 2459191Skris 2559191SkrisB<pod2man> converts its input file containing embedded pod directives (see 2659191SkrisL<perlpod>) into nroff source suitable for viewing with nroff(1) or 2759191Skristroff(1) using the man(7) macro set. 2859191Skris 2959191SkrisBesides the obvious pod conversions, B<pod2man> also takes care of 3059191Skrisfunc(), func(n), and simple variable references like $foo or @bar so 3159191Skrisyou don't have to use code escapes for them; complex expressions like 3259191SkrisC<$fred{'stuff'}> will still need to be escaped, though. Other nagging 3359191Skrislittle roffish things that it catches include translating the minus in 3459191Skrissomething like foo-bar, making a long dash--like this--into a real em 3559191Skrisdash, fixing up "paired quotes", putting a little space after the 3659191Skrisparens in something like func(), making C++ and PI look right, making 3759191Skrisdouble underbars have a little tiny space between them, making ALLCAPS 3859191Skrisa teeny bit smaller in troff(1), and escaping backslashes so you don't 3959191Skrishave to. 4059191Skris 4159191Skris=head1 OPTIONS 4259191Skris 4359191Skris=over 8 4459191Skris 4559191Skris=item center 4659191Skris 4759191SkrisSet the centered header to a specific string. The default is 4859191Skris"User Contributed Perl Documentation", unless the C<--official> flag is 4959191Skrisgiven, in which case the default is "Perl Programmers Reference Guide". 5059191Skris 5159191Skris=item date 5259191Skris 5359191SkrisSet the left-hand footer string to this value. By default, 5459191Skristhe modification date of the input file will be used. 5559191Skris 5659191Skris=item fixed 5759191Skris 5859191SkrisThe fixed font to use for code refs. Defaults to CW. 5959191Skris 6059191Skris=item official 6159191Skris 6259191SkrisSet the default header to indicate that this page is of 6359191Skristhe standard release in case C<--center> is not given. 6459191Skris 6559191Skris=item release 6659191Skris 6759191SkrisSet the centered footer. By default, this is the current 6859191Skrisperl release. 6959191Skris 7059191Skris=item section 7159191Skris 7259191SkrisSet the section for the C<.TH> macro. The standard conventions on 7359191Skrissections are to use 1 for user commands, 2 for system calls, 3 for 7459191Skrisfunctions, 4 for devices, 5 for file formats, 6 for games, 7 for 7559191Skrismiscellaneous information, and 8 for administrator commands. This works 7659191Skrisbest if you put your Perl man pages in a separate tree, like 7759191SkrisF</usr/local/perl/man/>. By default, section 1 will be used 7859191Skrisunless the file ends in F<.pm> in which case section 3 will be selected. 7959191Skris 8059191Skris=item lax 8159191Skris 8259191SkrisDon't complain when required sections aren't present. 8359191Skris 8459191Skris=back 8559191Skris 8659191Skris=head1 Anatomy of a Proper Man Page 8759191Skris 8859191SkrisFor those not sure of the proper layout of a man page, here's 8959191Skrisan example of the skeleton of a proper man page. Head of the 9059191Skrismajor headers should be setout as a C<=head1> directive, and 9159191Skrisare historically written in the rather startling ALL UPPER CASE 9259191Skrisformat, although this is not mandatory. 9359191SkrisMinor headers may be included using C<=head2>, and are 9459191Skristypically in mixed case. 9559191Skris 9659191Skris=over 10 9759191Skris 9859191Skris=item NAME 9959191Skris 10059191SkrisMandatory section; should be a comma-separated list of programs or 10159191Skrisfunctions documented by this podpage, such as: 10259191Skris 10359191Skris foo, bar - programs to do something 10459191Skris 10559191Skris=item SYNOPSIS 10659191Skris 10759191SkrisA short usage summary for programs and functions, which 10859191Skrismay someday be deemed mandatory. 10959191Skris 11059191Skris=item DESCRIPTION 11159191Skris 11259191SkrisLong drawn out discussion of the program. It's a good idea to break this 11359191Skrisup into subsections using the C<=head2> directives, like 11459191Skris 11559191Skris =head2 A Sample Subection 11659191Skris 11759191Skris =head2 Yet Another Sample Subection 11859191Skris 11959191Skris=item OPTIONS 12059191Skris 12159191SkrisSome people make this separate from the description. 12259191Skris 12359191Skris=item RETURN VALUE 12459191Skris 12559191SkrisWhat the program or function returns if successful. 12659191Skris 12759191Skris=item ERRORS 12859191Skris 12959191SkrisExceptions, return codes, exit stati, and errno settings. 13059191Skris 13159191Skris=item EXAMPLES 13259191Skris 13359191SkrisGive some example uses of the program. 13459191Skris 13559191Skris=item ENVIRONMENT 13659191Skris 13759191SkrisEnvariables this program might care about. 13859191Skris 13959191Skris=item FILES 14059191Skris 14159191SkrisAll files used by the program. You should probably use the FE<lt>E<gt> 14259191Skrisfor these. 14359191Skris 14459191Skris=item SEE ALSO 14559191Skris 14659191SkrisOther man pages to check out, like man(1), man(7), makewhatis(8), or catman(8). 14759191Skris 14859191Skris=item NOTES 14959191Skris 15059191SkrisMiscellaneous commentary. 15159191Skris 15259191Skris=item CAVEATS 15359191Skris 15459191SkrisThings to take special care with; sometimes called WARNINGS. 15559191Skris 15659191Skris=item DIAGNOSTICS 15759191Skris 15859191SkrisAll possible messages the program can print out--and 15959191Skriswhat they mean. 16059191Skris 16159191Skris=item BUGS 16259191Skris 16359191SkrisThings that are broken or just don't work quite right. 16459191Skris 16559191Skris=item RESTRICTIONS 16659191Skris 16759191SkrisBugs you don't plan to fix :-) 16859191Skris 16959191Skris=item AUTHOR 17059191Skris 17159191SkrisWho wrote it (or AUTHORS if multiple). 17259191Skris 17359191Skris=item HISTORY 17459191Skris 17559191SkrisPrograms derived from other sources sometimes have this, or 17659191Skrisyou might keep a modification log here. 17759191Skris 17859191Skris=back 17959191Skris 18059191Skris=head1 EXAMPLES 18159191Skris 18259191Skris pod2man program > program.1 18359191Skris pod2man some_module.pm > /usr/perl/man/man3/some_module.3 18459191Skris pod2man --section=7 note.pod > note.7 18559191Skris 18659191Skris=head1 DIAGNOSTICS 18759191Skris 18859191SkrisThe following diagnostics are generated by B<pod2man>. Items 18959191Skrismarked "(W)" are non-fatal, whereas the "(F)" errors will cause 19059191SkrisB<pod2man> to immediately exit with a non-zero status. 19159191Skris 19259191Skris=over 4 19359191Skris 19459191Skris=item bad option in paragraph %d of %s: ``%s'' should be [%s]<%s> 19559191Skris 19659191Skris(W) If you start include an option, you should set it off 19759191Skrisas bold, italic, or code. 19859191Skris 19959191Skris=item can't open %s: %s 20059191Skris 20159191Skris(F) The input file wasn't available for the given reason. 20259191Skris 20359191Skris=item Improper man page - no dash in NAME header in paragraph %d of %s 20459191Skris 20559191Skris(W) The NAME header did not have an isolated dash in it. This is 20659191Skrisconsidered important. 20759191Skris 20859191Skris=item Invalid man page - no NAME line in %s 20959191Skris 21059191Skris(F) You did not include a NAME header, which is essential. 21159191Skris 21259191Skris=item roff font should be 1 or 2 chars, not `%s' (F) 21359191Skris 21459191Skris(F) The font specified with the C<--fixed> option was not 21559191Skrisa one- or two-digit roff font. 21659191Skris 21759191Skris=item %s is missing required section: %s 21859191Skris 21959191Skris(W) Required sections include NAME, DESCRIPTION, and if you're 22059191Skrisusing a section starting with a 3, also a SYNOPSIS. Actually, 22159191Skrisnot having a NAME is a fatal. 22259191Skris 22359191Skris=item Unknown escape: %s in %s 22459191Skris 22559191Skris(W) An unknown HTML entity (probably for an 8-bit character) was given via 22659191Skrisa C<EE<lt>E<gt>> directive. Besides amp, lt, gt, and quot, recognized 22759191Skrisentities are Aacute, aacute, Acirc, acirc, AElig, aelig, Agrave, agrave, 22859191SkrisAring, aring, Atilde, atilde, Auml, auml, Ccedil, ccedil, Eacute, eacute, 22959191SkrisEcirc, ecirc, Egrave, egrave, ETH, eth, Euml, euml, Iacute, iacute, Icirc, 23059191Skrisicirc, Igrave, igrave, Iuml, iuml, Ntilde, ntilde, Oacute, oacute, Ocirc, 23159191Skrisocirc, Ograve, ograve, Oslash, oslash, Otilde, otilde, Ouml, ouml, szlig, 23259191SkrisTHORN, thorn, Uacute, uacute, Ucirc, ucirc, Ugrave, ugrave, Uuml, uuml, 23359191SkrisYacute, yacute, and yuml. 23459191Skris 23559191Skris=item Unmatched =back 23659191Skris 23759191Skris(W) You have a C<=back> without a corresponding C<=over>. 23859191Skris 23959191Skris=item Unrecognized pod directive: %s 24059191Skris 24159191Skris(W) You specified a pod directive that isn't in the known list of 24259191SkrisC<=head1>, C<=head2>, C<=item>, C<=over>, C<=back>, or C<=cut>. 24359191Skris 24459191Skris 24559191Skris=back 24659191Skris 24759191Skris=head1 NOTES 24859191Skris 24959191SkrisIf you would like to print out a lot of man page continuously, you 25059191Skrisprobably want to set the C and D registers to set contiguous page 25159191Skrisnumbering and even/odd paging, at least on some versions of man(7). 25259191SkrisSettting the F register will get you some additional experimental 25359191Skrisindexing: 25459191Skris 25559191Skris troff -man -rC1 -rD1 -rF1 perl.1 perldata.1 perlsyn.1 ... 25659191Skris 25759191SkrisThe indexing merely outputs messages via C<.tm> for each 25859191Skrismajor page, section, subsection, item, and any C<XE<lt>E<gt>> 25959191Skrisdirectives. 26059191Skris 26159191Skris 26259191Skris=head1 RESTRICTIONS 26359191Skris 26459191SkrisNone at this time. 26559191Skris 26659191Skris=head1 BUGS 26759191Skris 26859191SkrisThe =over and =back directives don't really work right. They 26959191Skristake absolute positions instead of offsets, don't nest well, and 27059191Skrismaking people count is suboptimal in any event. 27159191Skris 27259191Skris=head1 AUTHORS 27359191Skris 27459191SkrisOriginal prototype by Larry Wall, but so massively hacked over by 27559191SkrisTom Christiansen such that Larry probably doesn't recognize it anymore. 27659191Skris 27759191Skris=cut 27859191Skris 27959191Skris$/ = ""; 28059191Skris$cutting = 1; 28159191Skris@Indices = (); 28259191Skris 28359191Skris# We try first to get the version number from a local binary, in case we're 28459191Skris# running an installed version of Perl to produce documentation from an 28559191Skris# uninstalled newer version's pod files. 28659191Skrisif ($^O ne 'plan9' and $^O ne 'dos' and $^O ne 'os2' and $^O ne 'MSWin32') { 28759191Skris my $perl = (-x './perl' && -f './perl' ) ? 28859191Skris './perl' : 28959191Skris ((-x '../perl' && -f '../perl') ? 29059191Skris '../perl' : 29159191Skris ''); 29259191Skris ($version,$patch) = `$perl -e 'print $]'` =~ /^(\d\.\d{3})(\d{2})?/ if $perl; 29359191Skris} 29459191Skris# No luck; we'll just go with the running Perl's version 29559191Skris($version,$patch) = $] =~ /^(.{5})(\d{2})?/ unless $version; 29659191Skris$DEF_RELEASE = "perl $version"; 29759191Skris$DEF_RELEASE .= ", patch $patch" if $patch; 29859191Skris 29959191Skris 30059191Skrissub makedate { 30159191Skris my $secs = shift; 30259191Skris my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($secs); 30359191Skris my $mname = (qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec})[$mon]; 30459191Skris $year += 1900; 30559191Skris return "$mday/$mname/$year"; 30659191Skris} 30759191Skris 30859191Skrisuse Getopt::Long; 30959191Skris 31059191Skris$DEF_SECTION = 1; 31159191Skris$DEF_CENTER = "User Contributed Perl Documentation"; 31259191Skris$STD_CENTER = "Perl Programmers Reference Guide"; 31359191Skris$DEF_FIXED = 'CW'; 31459191Skris$DEF_LAX = 0; 31559191Skris 31659191Skrissub usage { 31759191Skris warn "$0: @_\n" if @_; 31859191Skris die <<EOF; 31959191Skrisusage: $0 [options] podpage 32059191SkrisOptions are: 32159191Skris --section=manext (default "$DEF_SECTION") 32259191Skris --release=relpatch (default "$DEF_RELEASE") 32359191Skris --center=string (default "$DEF_CENTER") 32459191Skris --date=string (default "$DEF_DATE") 32559191Skris --fixed=font (default "$DEF_FIXED") 32659191Skris --official (default NOT) 32759191Skris --lax (default NOT) 32859191SkrisEOF 32959191Skris} 33059191Skris 33159191Skris$uok = GetOptions( qw( 33259191Skris section=s 33359191Skris release=s 33459191Skris center=s 33559191Skris date=s 33659191Skris fixed=s 33759191Skris official 33859191Skris lax 33959191Skris help)); 34059191Skris 34159191Skris$DEF_DATE = makedate((stat($ARGV[0]))[9] || time()); 34259191Skris 34359191Skrisusage("Usage error!") unless $uok; 34459191Skrisusage() if $opt_help; 34559191Skrisusage("Need one and only one podpage argument") unless @ARGV == 1; 34659191Skris 34759191Skris$section = $opt_section || ($ARGV[0] =~ /\.pm$/ 34859191Skris ? $DEF_PM_SECTION : $DEF_SECTION); 34959191Skris$RP = $opt_release || $DEF_RELEASE; 35059191Skris$center = $opt_center || ($opt_official ? $STD_CENTER : $DEF_CENTER); 35159191Skris$lax = $opt_lax || $DEF_LAX; 35259191Skris 35359191Skris$CFont = $opt_fixed || $DEF_FIXED; 35459191Skris 35559191Skrisif (length($CFont) == 2) { 35659191Skris $CFont_embed = "\\f($CFont"; 35759191Skris} 35859191Skriselsif (length($CFont) == 1) { 35959191Skris $CFont_embed = "\\f$CFont"; 36059191Skris} 36159191Skriselse { 36259191Skris die "roff font should be 1 or 2 chars, not `$CFont_embed'"; 36359191Skris} 36459191Skris 36559191Skris$date = $opt_date || $DEF_DATE; 36659191Skris 36759191Skrisfor (qw{NAME DESCRIPTION}) { 36859191Skris# for (qw{NAME DESCRIPTION AUTHOR}) { 36959191Skris $wanna_see{$_}++; 37059191Skris} 37159191Skris$wanna_see{SYNOPSIS}++ if $section =~ /^3/; 37259191Skris 37359191Skris 37459191Skris$name = @ARGV ? $ARGV[0] : "<STDIN>"; 37559191Skris$Filename = $name; 37659191Skrisif ($section =~ /^1/) { 37759191Skris require File::Basename; 37859191Skris $name = uc File::Basename::basename($name); 37959191Skris} 38059191Skris$name =~ s/\.(pod|p[lm])$//i; 38159191Skris 38259191Skris# Lose everything up to the first of 38359191Skris# */lib/*perl* standard or site_perl module 38459191Skris# */*perl*/lib from -D prefix=/opt/perl 38559191Skris# */*perl*/ random module hierarchy 38659191Skris# which works. 38759191Skris$name =~ s-//+-/-g; 38859191Skrisif ($name =~ s-^.*?/lib/[^/]*perl[^/]*/--i 38959191Skris or $name =~ s-^.*?/[^/]*perl[^/]*/lib/--i 39059191Skris or $name =~ s-^.*?/[^/]*perl[^/]*/--i) { 39159191Skris # Lose ^site(_perl)?/. 39259191Skris $name =~ s-^site(_perl)?/--; 39359191Skris # Lose ^arch/. (XXX should we use Config? Just for archname?) 39459191Skris $name =~ s~^(.*-$^O|$^O-.*)/~~o; 39559191Skris # Lose ^version/. 39659191Skris $name =~ s-^\d+\.\d+/--; 39759191Skris} 39859191Skris 39959191Skris# Translate Getopt/Long to Getopt::Long, etc. 40059191Skris$name =~ s(/)(::)g; 40159191Skris 40259191Skrisif ($name ne 'something') { 40359191Skris FCHECK: { 40459191Skris open(F, "< $ARGV[0]") || die "can't open $ARGV[0]: $!"; 40559191Skris while (<F>) { 40659191Skris next unless /^=\b/; 40759191Skris if (/^=head1\s+NAME\s*$/) { # an /m would forgive mistakes 40859191Skris $_ = <F>; 40959191Skris unless (/\s*-+\s+/) { 41059191Skris $oops++; 41159191Skris warn "$0: Improper man page - no dash in NAME header in paragraph $. of $ARGV[0]\n" 41259191Skris } else { 41359191Skris my @n = split /\s+-+\s+/; 41459191Skris if (@n != 2) { 41559191Skris $oops++; 41659191Skris warn "$0: Improper man page - malformed NAME header in paragraph $. of $ARGV[0]\n" 41759191Skris } 41859191Skris else { 419100936Snectar $n[0] =~ s/\n/ /g; 420100936Snectar $n[1] =~ s/\n/ /g; 42159191Skris %namedesc = @n; 42259191Skris } 42359191Skris } 42459191Skris last FCHECK; 42559191Skris } 42659191Skris next if /^=cut\b/; # DB_File and Net::Ping have =cut before NAME 42759191Skris next if /^=pod\b/; # It is OK to have =pod before NAME 428205128Ssimon next if /^=(for|begin|end)\s+comment\b/; # It is OK to have =for =begin or =end comment before NAME 42959191Skris die "$0: Invalid man page - 1st pod line is not NAME in $ARGV[0]\n" unless $lax; 43059191Skris } 43159191Skris die "$0: Invalid man page - no documentation in $ARGV[0]\n" unless $lax; 43259191Skris } 43359191Skris close F; 43459191Skris} 43559191Skris 43659191Skrisprint <<"END"; 43759191Skris.rn '' }` 43859191Skris''' \$RCSfile\$\$Revision\$\$Date\$ 43959191Skris''' 44059191Skris''' \$Log\$ 44159191Skris''' 44259191Skris.de Sh 44359191Skris.br 44459191Skris.if t .Sp 44559191Skris.ne 5 44659191Skris.PP 44759191Skris\\fB\\\\\$1\\fR 44859191Skris.PP 44959191Skris.. 45059191Skris.de Sp 45159191Skris.if t .sp .5v 45259191Skris.if n .sp 45359191Skris.. 45459191Skris.de Ip 45559191Skris.br 45659191Skris.ie \\\\n(.\$>=3 .ne \\\\\$3 45759191Skris.el .ne 3 45859191Skris.IP "\\\\\$1" \\\\\$2 45959191Skris.. 46059191Skris.de Vb 46159191Skris.ft $CFont 46259191Skris.nf 46359191Skris.ne \\\\\$1 46459191Skris.. 46559191Skris.de Ve 46659191Skris.ft R 46759191Skris 46859191Skris.fi 46959191Skris.. 47059191Skris''' 47159191Skris''' 47259191Skris''' Set up \\*(-- to give an unbreakable dash; 47359191Skris''' string Tr holds user defined translation string. 47459191Skris''' Bell System Logo is used as a dummy character. 47559191Skris''' 47659191Skris.tr \\(*W-|\\(bv\\*(Tr 47759191Skris.ie n \\{\\ 47859191Skris.ds -- \\(*W- 47959191Skris.ds PI pi 48059191Skris.if (\\n(.H=4u)&(1m=24u) .ds -- \\(*W\\h'-12u'\\(*W\\h'-12u'-\\" diablo 10 pitch 48159191Skris.if (\\n(.H=4u)&(1m=20u) .ds -- \\(*W\\h'-12u'\\(*W\\h'-8u'-\\" diablo 12 pitch 48259191Skris.ds L" "" 48359191Skris.ds R" "" 48459191Skris''' \\*(M", \\*(S", \\*(N" and \\*(T" are the equivalent of 48559191Skris''' \\*(L" and \\*(R", except that they are used on ".xx" lines, 48659191Skris''' such as .IP and .SH, which do another additional levels of 48759191Skris''' double-quote interpretation 48859191Skris.ds M" """ 48959191Skris.ds S" """ 49059191Skris.ds N" """"" 49159191Skris.ds T" """"" 49259191Skris.ds L' ' 49359191Skris.ds R' ' 49459191Skris.ds M' ' 49559191Skris.ds S' ' 49659191Skris.ds N' ' 49759191Skris.ds T' ' 49859191Skris'br\\} 49959191Skris.el\\{\\ 50059191Skris.ds -- \\(em\\| 50159191Skris.tr \\*(Tr 50259191Skris.ds L" `` 50359191Skris.ds R" '' 50459191Skris.ds M" `` 50559191Skris.ds S" '' 50659191Skris.ds N" `` 50759191Skris.ds T" '' 50859191Skris.ds L' ` 50959191Skris.ds R' ' 51059191Skris.ds M' ` 51159191Skris.ds S' ' 51259191Skris.ds N' ` 51359191Skris.ds T' ' 51459191Skris.ds PI \\(*p 51559191Skris'br\\} 51659191SkrisEND 51759191Skris 51859191Skrisprint <<'END'; 51959191Skris.\" If the F register is turned on, we'll generate 52059191Skris.\" index entries out stderr for the following things: 52159191Skris.\" TH Title 52259191Skris.\" SH Header 52359191Skris.\" Sh Subsection 52459191Skris.\" Ip Item 52559191Skris.\" X<> Xref (embedded 52659191Skris.\" Of course, you have to process the output yourself 52759191Skris.\" in some meaninful fashion. 52859191Skris.if \nF \{ 52959191Skris.de IX 53059191Skris.tm Index:\\$1\t\\n%\t"\\$2" 53159191Skris.. 53259191Skris.nr % 0 53359191Skris.rr F 53459191Skris.\} 53559191SkrisEND 53659191Skris 53759191Skrisprint <<"END"; 53859191Skris.TH $name $section "$RP" "$date" "$center" 53959191Skris.UC 54059191SkrisEND 54159191Skris 54259191Skrispush(@Indices, qq{.IX Title "$name $section"}); 54359191Skris 54459191Skriswhile (($name, $desc) = each %namedesc) { 54559191Skris for ($name, $desc) { s/^\s+//; s/\s+$//; } 54659191Skris push(@Indices, qq(.IX Name "$name - $desc"\n)); 54759191Skris} 54859191Skris 54959191Skrisprint <<'END'; 55059191Skris.if n .hy 0 55159191Skris.if n .na 55259191Skris.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 55359191Skris.de CQ \" put $1 in typewriter font 55459191SkrisEND 55559191Skrisprint ".ft $CFont\n"; 55659191Skrisprint <<'END'; 55759191Skris'if n "\c 55859191Skris'if t \\&\\$1\c 55959191Skris'if n \\&\\$1\c 56059191Skris'if n \&" 56159191Skris\\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 56259191Skris'.ft R 56359191Skris.. 56459191Skris.\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 56559191Skris. \" AM - accent mark definitions 56659191Skris.bd B 3 56759191Skris. \" fudge factors for nroff and troff 56859191Skris.if n \{\ 56959191Skris. ds #H 0 57059191Skris. ds #V .8m 57159191Skris. ds #F .3m 57259191Skris. ds #[ \f1 57359191Skris. ds #] \fP 57459191Skris.\} 57559191Skris.if t \{\ 57659191Skris. ds #H ((1u-(\\\\n(.fu%2u))*.13m) 57759191Skris. ds #V .6m 57859191Skris. ds #F 0 57959191Skris. ds #[ \& 58059191Skris. ds #] \& 58159191Skris.\} 58259191Skris. \" simple accents for nroff and troff 58359191Skris.if n \{\ 58459191Skris. ds ' \& 58559191Skris. ds ` \& 58659191Skris. ds ^ \& 58759191Skris. ds , \& 58859191Skris. ds ~ ~ 58959191Skris. ds ? ? 59059191Skris. ds ! ! 59159191Skris. ds / 59259191Skris. ds q 59359191Skris.\} 59459191Skris.if t \{\ 59559191Skris. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 59659191Skris. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 59759191Skris. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 59859191Skris. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 59959191Skris. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 60059191Skris. ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' 60159191Skris. ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' 60259191Skris. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 60359191Skris. 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' 60459191Skris.\} 60559191Skris. \" troff and (daisy-wheel) nroff accents 60659191Skris.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 60759191Skris.ds 8 \h'\*(#H'\(*b\h'-\*(#H' 60859191Skris.ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] 60959191Skris.ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' 61059191Skris.ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' 61159191Skris.ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] 61259191Skris.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 61359191Skris.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 61459191Skris.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 61559191Skris.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 61659191Skris.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 61759191Skris.ds ae a\h'-(\w'a'u*4/10)'e 61859191Skris.ds Ae A\h'-(\w'A'u*4/10)'E 61959191Skris.ds oe o\h'-(\w'o'u*4/10)'e 62059191Skris.ds Oe O\h'-(\w'O'u*4/10)'E 62159191Skris. \" corrections for vroff 62259191Skris.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 62359191Skris.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 62459191Skris. \" for low resolution devices (crt and lpr) 62559191Skris.if \n(.H>23 .if \n(.V>19 \ 62659191Skris\{\ 62759191Skris. ds : e 62859191Skris. ds 8 ss 62959191Skris. ds v \h'-1'\o'\(aa\(ga' 63059191Skris. ds _ \h'-1'^ 63159191Skris. ds . \h'-1'. 63259191Skris. ds 3 3 63359191Skris. ds o a 63459191Skris. ds d- d\h'-1'\(ga 63559191Skris. ds D- D\h'-1'\(hy 63659191Skris. ds th \o'bp' 63759191Skris. ds Th \o'LP' 63859191Skris. ds ae ae 63959191Skris. ds Ae AE 64059191Skris. ds oe oe 64159191Skris. ds Oe OE 64259191Skris.\} 64359191Skris.rm #[ #] #H #V #F C 64459191SkrisEND 64559191Skris 64659191Skris$indent = 0; 64759191Skris 64859191Skris$begun = ""; 64959191Skris 65059191Skris# Unrolling [^A-Z>]|[A-Z](?!<) gives: // MRE pp 165. 65159191Skrismy $nonest = '(?:[^A-Z>]*(?:[A-Z](?!<)[^A-Z>]*)*)'; 65259191Skris 65359191Skriswhile (<>) { 65459191Skris if ($cutting) { 65559191Skris next unless /^=/; 65659191Skris $cutting = 0; 65759191Skris } 65859191Skris if ($begun) { 65959191Skris if (/^=end\s+$begun/) { 66059191Skris $begun = ""; 66159191Skris } 66259191Skris elsif ($begun =~ /^(roff|man)$/) { 66359191Skris print STDOUT $_; 66459191Skris } 66559191Skris next; 66659191Skris } 66759191Skris chomp; 66859191Skris 66959191Skris # Translate verbatim paragraph 67059191Skris 67159191Skris if (/^\s/) { 67259191Skris @lines = split(/\n/); 67359191Skris for (@lines) { 67459191Skris 1 while s 67559191Skris {^( [^\t]* ) \t ( \t* ) } 67659191Skris { $1 . ' ' x (8 - (length($1)%8) + 8 * (length($2))) }ex; 67759191Skris s/\\/\\e/g; 67859191Skris s/\A/\\&/s; 67959191Skris } 68059191Skris $lines = @lines; 68159191Skris makespace() unless $verbatim++; 68259191Skris print ".Vb $lines\n"; 68359191Skris print join("\n", @lines), "\n"; 68459191Skris print ".Ve\n"; 68559191Skris $needspace = 0; 68659191Skris next; 68759191Skris } 68859191Skris 68959191Skris $verbatim = 0; 69059191Skris 69159191Skris if (/^=for\s+(\S+)\s*/s) { 69259191Skris if ($1 eq "man" or $1 eq "roff") { 69359191Skris print STDOUT $',"\n\n"; 69459191Skris } else { 69559191Skris # ignore unknown for 69659191Skris } 69759191Skris next; 69859191Skris } 69959191Skris elsif (/^=begin\s+(\S+)\s*/s) { 70059191Skris $begun = $1; 70159191Skris if ($1 eq "man" or $1 eq "roff") { 70259191Skris print STDOUT $'."\n\n"; 70359191Skris } 70459191Skris next; 70559191Skris } 70659191Skris 70759191Skris # check for things that'll hosed our noremap scheme; affects $_ 70859191Skris init_noremap(); 70959191Skris 71059191Skris if (!/^=item/) { 71159191Skris 71259191Skris # trofficate backslashes; must do it before what happens below 71359191Skris s/\\/noremap('\\e')/ge; 71459191Skris 71559191Skris # protect leading periods and quotes against *roff 71659191Skris # mistaking them for directives 71759191Skris s/^(?:[A-Z]<)?[.']/\\&$&/gm; 71859191Skris 71959191Skris # first hide the escapes in case we need to 72059191Skris # intuit something and get it wrong due to fmting 72159191Skris 72259191Skris 1 while s/([A-Z]<$nonest>)/noremap($1)/ge; 72359191Skris 72459191Skris # func() is a reference to a perl function 72559191Skris s{ 72659191Skris \b 72759191Skris ( 72859191Skris [:\w]+ \(\) 72959191Skris ) 73059191Skris } {I<$1>}gx; 73159191Skris 73259191Skris # func(n) is a reference to a perl function or a man page 73359191Skris s{ 73459191Skris ([:\w]+) 73559191Skris ( 73659191Skris \( [^\051]+ \) 73759191Skris ) 73859191Skris } {I<$1>\\|$2}gx; 73959191Skris 74059191Skris # convert simple variable references 74159191Skris s/(\s+)([\$\@%][\w:]+)(?!\()/${1}C<$2>/g; 74259191Skris 74359191Skris if (m{ ( 74459191Skris [\-\w]+ 74559191Skris \( 74659191Skris [^\051]*? 74759191Skris [\@\$,] 74859191Skris [^\051]*? 74959191Skris \) 75059191Skris ) 75159191Skris }x && $` !~ /([LCI]<[^<>]*|-)$/ && !/^=\w/) 75259191Skris { 75359191Skris warn "$0: bad option in paragraph $. of $ARGV: ``$1'' should be [LCI]<$1>\n"; 75459191Skris $oops++; 75559191Skris } 75659191Skris 75759191Skris while (/(-[a-zA-Z])\b/g && $` !~ /[\w\-]$/) { 75859191Skris warn "$0: bad option in paragraph $. of $ARGV: ``$1'' should be [CB]<$1>\n"; 75959191Skris $oops++; 76059191Skris } 76159191Skris 76259191Skris # put it back so we get the <> processed again; 76359191Skris clear_noremap(0); # 0 means leave the E's 76459191Skris 76559191Skris } else { 76659191Skris # trofficate backslashes 76759191Skris s/\\/noremap('\\e')/ge; 76859191Skris 76959191Skris } 77059191Skris 77159191Skris # need to hide E<> first; they're processed in clear_noremap 77259191Skris s/(E<[^<>]+>)/noremap($1)/ge; 77359191Skris 77459191Skris 77559191Skris $maxnest = 10; 77659191Skris while ($maxnest-- && /[A-Z]</) { 77759191Skris 77859191Skris # can't do C font here 77959191Skris s/([BI])<($nonest)>/font($1) . $2 . font('R')/eg; 78059191Skris 78159191Skris # files and filelike refs in italics 78259191Skris s/F<($nonest)>/I<$1>/g; 78359191Skris 78459191Skris # no break -- usually we want C<> for this 78559191Skris s/S<($nonest)>/nobreak($1)/eg; 78659191Skris 78759191Skris # LREF: a la HREF L<show this text|man/section> 78859191Skris s:L<([^|>]+)\|[^>]+>:$1:g; 78959191Skris 79059191Skris # LREF: a manpage(3f) 79159191Skris s:L<([a-zA-Z][^\s\/]+)(\([^\)]+\))?>:the I<$1>$2 manpage:g; 79259191Skris 79359191Skris # LREF: an =item on another manpage 79459191Skris s{ 79559191Skris L< 79659191Skris ([^/]+) 79759191Skris / 79859191Skris ( 79959191Skris [:\w]+ 80059191Skris (\(\))? 80159191Skris ) 80259191Skris > 80359191Skris } {the C<$2> entry in the I<$1> manpage}gx; 80459191Skris 80559191Skris # LREF: an =item on this manpage 80659191Skris s{ 80759191Skris ((?: 80859191Skris L< 80959191Skris / 81059191Skris ( 81159191Skris [:\w]+ 81259191Skris (\(\))? 81359191Skris ) 81459191Skris > 81559191Skris (,?\s+(and\s+)?)? 81659191Skris )+) 81759191Skris } { internal_lrefs($1) }gex; 81859191Skris 81959191Skris # LREF: a =head2 (head1?), maybe on a manpage, maybe right here 82059191Skris # the "func" can disambiguate 82159191Skris s{ 82259191Skris L< 82359191Skris (?: 82459191Skris ([a-zA-Z]\S+?) / 82559191Skris )? 82659191Skris "?(.*?)"? 82759191Skris > 82859191Skris }{ 82959191Skris do { 83059191Skris $1 # if no $1, assume it means on this page. 83159191Skris ? "the section on I<$2> in the I<$1> manpage" 83259191Skris : "the section on I<$2>" 83359191Skris } 83459191Skris }gesx; # s in case it goes over multiple lines, so . matches \n 83559191Skris 83659191Skris s/Z<>/\\&/g; 83759191Skris 83859191Skris # comes last because not subject to reprocessing 83959191Skris s/C<($nonest)>/noremap("${CFont_embed}${1}\\fR")/eg; 84059191Skris } 84159191Skris 84259191Skris if (s/^=//) { 84359191Skris $needspace = 0; # Assume this. 84459191Skris 84559191Skris s/\n/ /g; 84659191Skris 84759191Skris ($Cmd, $_) = split(' ', $_, 2); 84859191Skris 84959191Skris $dotlevel = 1; 85059191Skris if ($Cmd eq 'head1') { 85159191Skris $dotlevel = 1; 85259191Skris } 85359191Skris elsif ($Cmd eq 'head2') { 85459191Skris $dotlevel = 1; 85559191Skris } 85659191Skris elsif ($Cmd eq 'item') { 85759191Skris $dotlevel = 2; 85859191Skris } 85959191Skris 86059191Skris if (defined $_) { 86159191Skris &escapes($dotlevel); 86259191Skris s/"/""/g; 86359191Skris } 86459191Skris 86559191Skris clear_noremap(1); 86659191Skris 86759191Skris if ($Cmd eq 'cut') { 86859191Skris $cutting = 1; 86959191Skris } 87059191Skris elsif ($Cmd eq 'head1') { 87159191Skris s/\s+$//; 87259191Skris delete $wanna_see{$_} if exists $wanna_see{$_}; 87359191Skris print qq{.SH "$_"\n}; 87459191Skris push(@Indices, qq{.IX Header "$_"\n}); 87559191Skris } 87659191Skris elsif ($Cmd eq 'head2') { 87759191Skris print qq{.Sh "$_"\n}; 87859191Skris push(@Indices, qq{.IX Subsection "$_"\n}); 87959191Skris } 88059191Skris elsif ($Cmd eq 'over') { 88159191Skris push(@indent,$indent); 88259191Skris $indent += ($_ + 0) || 5; 88359191Skris } 88459191Skris elsif ($Cmd eq 'back') { 88559191Skris $indent = pop(@indent); 88659191Skris warn "$0: Unmatched =back in paragraph $. of $ARGV\n" unless defined $indent; 88759191Skris $needspace = 1; 88859191Skris } 88959191Skris elsif ($Cmd eq 'item') { 89059191Skris s/^\*( |$)/\\(bu$1/g; 89159191Skris # if you know how to get ":s please do 89259191Skris s/\\\*\(L"([^"]+?)\\\*\(R"/'$1'/g; 89359191Skris s/\\\*\(L"([^"]+?)""/'$1'/g; 89459191Skris s/[^"]""([^"]+?)""[^"]/'$1'/g; 89559191Skris # here do something about the $" in perlvar? 89659191Skris print STDOUT qq{.Ip "$_" $indent\n}; 89759191Skris push(@Indices, qq{.IX Item "$_"\n}); 89859191Skris } 89959191Skris elsif ($Cmd eq 'pod') { 90059191Skris # this is just a comment 90159191Skris } 90259191Skris else { 90359191Skris warn "$0: Unrecognized pod directive in paragraph $. of $ARGV: $Cmd\n"; 90459191Skris } 90559191Skris } 90659191Skris else { 90759191Skris if ($needspace) { 90859191Skris &makespace; 90959191Skris } 91059191Skris &escapes(0); 91159191Skris clear_noremap(1); 91259191Skris print $_, "\n"; 91359191Skris $needspace = 1; 91459191Skris } 91559191Skris} 91659191Skris 91759191Skrisprint <<"END"; 91859191Skris 91959191Skris.rn }` '' 92059191SkrisEND 92159191Skris 92259191Skrisif (%wanna_see && !$lax) { 92359191Skris @missing = keys %wanna_see; 92459191Skris warn "$0: $Filename is missing required section" 92559191Skris . (@missing > 1 && "s") 92659191Skris . ": @missing\n"; 92759191Skris $oops++; 92859191Skris} 92959191Skris 93059191Skrisforeach (@Indices) { print "$_\n"; } 93159191Skris 93259191Skrisexit; 93359191Skris#exit ($oops != 0); 93459191Skris 93559191Skris######################################################################### 93659191Skris 93759191Skrissub nobreak { 93859191Skris my $string = shift; 93959191Skris $string =~ s/ /\\ /g; 94059191Skris $string; 94159191Skris} 94259191Skris 94359191Skrissub escapes { 94459191Skris my $indot = shift; 94559191Skris 94659191Skris s/X<(.*?)>/mkindex($1)/ge; 94759191Skris 94859191Skris # translate the minus in foo-bar into foo\-bar for roff 94959191Skris s/([^0-9a-z-])-([^-])/$1\\-$2/g; 95059191Skris 95159191Skris # make -- into the string version \*(-- (defined above) 95259191Skris s/\b--\b/\\*(--/g; 95359191Skris s/"--([^"])/"\\*(--$1/g; # should be a better way 95459191Skris s/([^"])--"/$1\\*(--"/g; 95559191Skris 95659191Skris # fix up quotes; this is somewhat tricky 95759191Skris my $dotmacroL = 'L'; 95859191Skris my $dotmacroR = 'R'; 95959191Skris if ( $indot == 1 ) { 96059191Skris $dotmacroL = 'M'; 96159191Skris $dotmacroR = 'S'; 96259191Skris } 96359191Skris elsif ( $indot >= 2 ) { 96459191Skris $dotmacroL = 'N'; 96559191Skris $dotmacroR = 'T'; 96659191Skris } 96759191Skris if (!/""/) { 96859191Skris s/(^|\s)(['"])/noremap("$1\\*($dotmacroL$2")/ge; 96959191Skris s/(['"])($|[\-\s,;\\!?.])/noremap("\\*($dotmacroR$1$2")/ge; 97059191Skris } 97159191Skris 97259191Skris #s/(?!")(?:.)--(?!")(?:.)/\\*(--/g; 97359191Skris #s/(?:(?!")(?:.)--(?:"))|(?:(?:")--(?!")(?:.))/\\*(--/g; 97459191Skris 97559191Skris 97659191Skris # make sure that func() keeps a bit a space tween the parens 97759191Skris ### s/\b\(\)/\\|()/g; 97859191Skris ### s/\b\(\)/(\\|)/g; 97959191Skris 98059191Skris # make C++ into \*C+, which is a squinched version (defined above) 98159191Skris s/\bC\+\+/\\*(C+/g; 98259191Skris 98359191Skris # make double underbars have a little tiny space between them 98459191Skris s/__/_\\|_/g; 98559191Skris 98659191Skris # PI goes to \*(PI (defined above) 98759191Skris s/\bPI\b/noremap('\\*(PI')/ge; 98859191Skris 98959191Skris # make all caps a teeny bit smaller, but don't muck with embedded code literals 99059191Skris my $hidCFont = font('C'); 99159191Skris if ($Cmd !~ /^head1/) { # SH already makes smaller 99259191Skris # /g isn't enough; 1 while or we'll be off 99359191Skris 99459191Skris# 1 while s{ 99559191Skris# (?!$hidCFont)(..|^.|^) 99659191Skris# \b 99759191Skris# ( 99859191Skris# [A-Z][\/A-Z+:\-\d_$.]+ 99959191Skris# ) 100059191Skris# (s?) 100159191Skris# \b 100259191Skris# } {$1\\s-1$2\\s0}gmox; 100359191Skris 100459191Skris 1 while s{ 100559191Skris (?!$hidCFont)(..|^.|^) 100659191Skris ( 100759191Skris \b[A-Z]{2,}[\/A-Z+:\-\d_\$]*\b 100859191Skris ) 100959191Skris } { 101059191Skris $1 . noremap( '\\s-1' . $2 . '\\s0' ) 101159191Skris }egmox; 101259191Skris 101359191Skris } 101459191Skris} 101559191Skris 101659191Skris# make troff just be normal, but make small nroff get quoted 101759191Skris# decided to just put the quotes in the text; sigh; 101859191Skrissub ccvt { 101959191Skris local($_,$prev) = @_; 102059191Skris noremap(qq{.CQ "$_" \n\\&}); 102159191Skris} 102259191Skris 102359191Skrissub makespace { 102459191Skris if ($indent) { 102559191Skris print ".Sp\n"; 102659191Skris } 102759191Skris else { 102859191Skris print ".PP\n"; 102959191Skris } 103059191Skris} 103159191Skris 103259191Skrissub mkindex { 103359191Skris my ($entry) = @_; 103459191Skris my @entries = split m:\s*/\s*:, $entry; 103559191Skris push @Indices, ".IX Xref " . join ' ', map {qq("$_")} @entries; 103659191Skris return ''; 103759191Skris} 103859191Skris 103959191Skrissub font { 104059191Skris local($font) = shift; 104159191Skris return '\\f' . noremap($font); 104259191Skris} 104359191Skris 104459191Skrissub noremap { 104559191Skris local($thing_to_hide) = shift; 104659191Skris $thing_to_hide =~ tr/\000-\177/\200-\377/; 104759191Skris return $thing_to_hide; 104859191Skris} 104959191Skris 105059191Skrissub init_noremap { 105159191Skris # escape high bit characters in input stream 105259191Skris s/([\200-\377])/"E<".ord($1).">"/ge; 105359191Skris} 105459191Skris 105559191Skrissub clear_noremap { 105659191Skris my $ready_to_print = $_[0]; 105759191Skris 105859191Skris tr/\200-\377/\000-\177/; 105959191Skris 106059191Skris # trofficate backslashes 106159191Skris # s/(?!\\e)(?:..|^.|^)\\/\\e/g; 106259191Skris 106359191Skris # now for the E<>s, which have been hidden until now 106459191Skris # otherwise the interative \w<> processing would have 106559191Skris # been hosed by the E<gt> 106659191Skris s { 106759191Skris E< 106859191Skris ( 106959191Skris ( \d + ) 107059191Skris | ( [A-Za-z]+ ) 107159191Skris ) 107259191Skris > 107359191Skris } { 107459191Skris do { 107559191Skris defined $2 107659191Skris ? chr($2) 107759191Skris : 107859191Skris exists $HTML_Escapes{$3} 107959191Skris ? do { $HTML_Escapes{$3} } 108059191Skris : do { 108159191Skris warn "$0: Unknown escape in paragraph $. of $ARGV: ``$&''\n"; 108259191Skris "E<$1>"; 108359191Skris } 108459191Skris } 108559191Skris }egx if $ready_to_print; 108659191Skris} 108759191Skris 108859191Skrissub internal_lrefs { 108959191Skris local($_) = shift; 109059191Skris local $trailing_and = s/and\s+$// ? "and " : ""; 109159191Skris 109259191Skris s{L</([^>]+)>}{$1}g; 109359191Skris my(@items) = split( /(?:,?\s+(?:and\s+)?)/ ); 109459191Skris my $retstr = "the "; 109559191Skris my $i; 109659191Skris for ($i = 0; $i <= $#items; $i++) { 109759191Skris $retstr .= "C<$items[$i]>"; 109859191Skris $retstr .= ", " if @items > 2 && $i != $#items; 109959191Skris $retstr .= " and " if $i+2 == @items; 110059191Skris } 110159191Skris 110259191Skris $retstr .= " entr" . ( @items > 1 ? "ies" : "y" ) 110359191Skris . " elsewhere in this document"; 110459191Skris # terminal space to avoid words running together (pattern used 110559191Skris # strips terminal spaces) 110659191Skris $retstr .= " " if length $trailing_and; 110759191Skris $retstr .= $trailing_and; 110859191Skris 110959191Skris return $retstr; 111059191Skris 111159191Skris} 111259191Skris 111359191SkrisBEGIN { 111459191Skris%HTML_Escapes = ( 111559191Skris 'amp' => '&', # ampersand 111659191Skris 'lt' => '<', # left chevron, less-than 111759191Skris 'gt' => '>', # right chevron, greater-than 111859191Skris 'quot' => '"', # double quote 111959191Skris 112059191Skris "Aacute" => "A\\*'", # capital A, acute accent 112159191Skris "aacute" => "a\\*'", # small a, acute accent 112259191Skris "Acirc" => "A\\*^", # capital A, circumflex accent 112359191Skris "acirc" => "a\\*^", # small a, circumflex accent 112459191Skris "AElig" => '\*(AE', # capital AE diphthong (ligature) 112559191Skris "aelig" => '\*(ae', # small ae diphthong (ligature) 112659191Skris "Agrave" => "A\\*`", # capital A, grave accent 112759191Skris "agrave" => "A\\*`", # small a, grave accent 112859191Skris "Aring" => 'A\\*o', # capital A, ring 112959191Skris "aring" => 'a\\*o', # small a, ring 113059191Skris "Atilde" => 'A\\*~', # capital A, tilde 113159191Skris "atilde" => 'a\\*~', # small a, tilde 113259191Skris "Auml" => 'A\\*:', # capital A, dieresis or umlaut mark 113359191Skris "auml" => 'a\\*:', # small a, dieresis or umlaut mark 113459191Skris "Ccedil" => 'C\\*,', # capital C, cedilla 113559191Skris "ccedil" => 'c\\*,', # small c, cedilla 113659191Skris "Eacute" => "E\\*'", # capital E, acute accent 113759191Skris "eacute" => "e\\*'", # small e, acute accent 113859191Skris "Ecirc" => "E\\*^", # capital E, circumflex accent 113959191Skris "ecirc" => "e\\*^", # small e, circumflex accent 114059191Skris "Egrave" => "E\\*`", # capital E, grave accent 114159191Skris "egrave" => "e\\*`", # small e, grave accent 114259191Skris "ETH" => '\\*(D-', # capital Eth, Icelandic 114359191Skris "eth" => '\\*(d-', # small eth, Icelandic 114459191Skris "Euml" => "E\\*:", # capital E, dieresis or umlaut mark 114559191Skris "euml" => "e\\*:", # small e, dieresis or umlaut mark 114659191Skris "Iacute" => "I\\*'", # capital I, acute accent 114759191Skris "iacute" => "i\\*'", # small i, acute accent 114859191Skris "Icirc" => "I\\*^", # capital I, circumflex accent 114959191Skris "icirc" => "i\\*^", # small i, circumflex accent 115059191Skris "Igrave" => "I\\*`", # capital I, grave accent 115159191Skris "igrave" => "i\\*`", # small i, grave accent 115259191Skris "Iuml" => "I\\*:", # capital I, dieresis or umlaut mark 115359191Skris "iuml" => "i\\*:", # small i, dieresis or umlaut mark 115459191Skris "Ntilde" => 'N\*~', # capital N, tilde 115559191Skris "ntilde" => 'n\*~', # small n, tilde 115659191Skris "Oacute" => "O\\*'", # capital O, acute accent 115759191Skris "oacute" => "o\\*'", # small o, acute accent 115859191Skris "Ocirc" => "O\\*^", # capital O, circumflex accent 115959191Skris "ocirc" => "o\\*^", # small o, circumflex accent 116059191Skris "Ograve" => "O\\*`", # capital O, grave accent 116159191Skris "ograve" => "o\\*`", # small o, grave accent 116259191Skris "Oslash" => "O\\*/", # capital O, slash 116359191Skris "oslash" => "o\\*/", # small o, slash 116459191Skris "Otilde" => "O\\*~", # capital O, tilde 116559191Skris "otilde" => "o\\*~", # small o, tilde 116659191Skris "Ouml" => "O\\*:", # capital O, dieresis or umlaut mark 116759191Skris "ouml" => "o\\*:", # small o, dieresis or umlaut mark 116859191Skris "szlig" => '\*8', # small sharp s, German (sz ligature) 116959191Skris "THORN" => '\\*(Th', # capital THORN, Icelandic 117059191Skris "thorn" => '\\*(th',, # small thorn, Icelandic 117159191Skris "Uacute" => "U\\*'", # capital U, acute accent 117259191Skris "uacute" => "u\\*'", # small u, acute accent 117359191Skris "Ucirc" => "U\\*^", # capital U, circumflex accent 117459191Skris "ucirc" => "u\\*^", # small u, circumflex accent 117559191Skris "Ugrave" => "U\\*`", # capital U, grave accent 117659191Skris "ugrave" => "u\\*`", # small u, grave accent 117759191Skris "Uuml" => "U\\*:", # capital U, dieresis or umlaut mark 117859191Skris "uuml" => "u\\*:", # small u, dieresis or umlaut mark 117959191Skris "Yacute" => "Y\\*'", # capital Y, acute accent 118059191Skris "yacute" => "y\\*'", # small y, acute accent 118159191Skris "yuml" => "y\\*:", # small y, dieresis or umlaut mark 118259191Skris); 118359191Skris} 118459191Skris 1185