#!/usr/bin/perl ### ### Quick usage: mdoc2man.pl < mdoc_manpage.8 > man_manpage.8 ### ### ### Copyright (c) 2001 University of Illinois Board of Trustees ### Copyright (c) 2001 Mark D. Roth ### All rights reserved. ### ### Redistribution and use in source and binary forms, with or without ### modification, are permitted provided that the following conditions ### are met: ### 1. Redistributions of source code must retain the above copyright ### notice, this list of conditions and the following disclaimer. ### 2. Redistributions in binary form must reproduce the above copyright ### notice, this list of conditions and the following disclaimer in the ### documentation and/or other materials provided with the distribution. ### 3. All advertising materials mentioning features or use of this software ### must display the following acknowledgement: ### This product includes software developed by the University of ### Illinois at Urbana, and their contributors. ### 4. The University nor the names of their ### contributors may be used to endorse or promote products derived from ### this software without specific prior written permission. ### ### THIS SOFTWARE IS PROVIDED BY THE TRUSTEES AND CONTRIBUTORS ``AS IS'' AND ### ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ### IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ### ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTEES OR CONTRIBUTORS BE LIABLE ### FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ### DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ### OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ### HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ### LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ### OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ### SUCH DAMAGE. ### use strict; my ($name, $date, $id); my ($line); my ($optlist, $oldoptlist, $nospace, $enum, $synopsis); my ($reference, $block, $ext, $extopt, $literal); my (@refauthors, $reftitle, $refissue, $refdate, $refopt); $optlist = 0; ### 1 = bullet, 2 = enum, 3 = tag, 4 = item $oldoptlist = 0; $nospace = 0; $synopsis = 0; $reference = 0; $block = 0; $ext = 0; $extopt = 0; $literal = 0; while ($line = ) { if ($line !~ /^\./) { print $line; print ".br\n" if ($literal); next; } $line =~ s/^\.//; next if ($line =~ m/\\"/); $line = ParseMacro($line); print($line) if (defined $line); } sub ParseMacro # ($line) { my ($line) = @_; my (@words, $retval, $option, $parens); @words = split(/\s+/, $line); $retval = ''; $option = 0; $parens = 0; # print('@words = ', scalar(@words), ': ', join(' ', @words), "\n"); while ($_ = shift @words) { # print "WORD: $_\n"; next if (/^(Li|Pf)$/); if (/^Xo$/) { $ext = 1; $retval .= ' ' if ($retval ne '' && $retval !~ m/[\n ]$/); next; } if (/^Xc$/) { $ext = 0; $retval .= "\n" if (! $extopt); last; } if (/^Bd$/) { $literal = 1 if ($words[0] eq '-literal'); $retval .= "\n"; last; } if (/^Ed$/) { $literal = 0; last; } if (/^Ns$/) { $nospace = 1 if (! $nospace); $retval =~ s/ $//; next; } if (/^No$/) { $retval =~ s/ $//; $retval .= shift @words; next; } if (/^Dq$/) { $retval .= '``'; do { $retval .= (shift @words) . ' '; } while (@words > 0 && $words[0] !~ m/^[\.,]/); $retval =~ s/ $//; $retval .= '\'\''; $nospace = 1 if (! $nospace && $words[0] =~ m/^[\.,]/); next; } if (/^(Sq|Ql)$/) { $retval .= '`' . (shift @words) . '\''; $nospace = 1 if (! $nospace && $words[0] =~ m/^[\.,]/); next; } # if (/^Ic$/) # { # $retval .= '\\fB' . shift(@words) . '\\fP'; # next; # } if (/^Oo$/) { # $retval .= "[\\c\n"; $extopt = 1; $nospace = 1 if (! $nospace); $retval .= '['; next; } if (/^Oc$/) { $extopt = 0; $retval .= ']'; next; } $retval .= ' ' if (! $nospace && $retval ne '' && $retval !~ m/[\n ]$/); $nospace = 0 if ($nospace == 1); if (/^Dd$/) { $date = join(' ', @words); return undef; } if (/^Dt$/) { $id = join(' ', @words); return undef; } if (/^Os$/) { $retval .= '.TH ' . $id . " \"$date\" \"" . join(' ', @words) . "\""; last; } if (/^Sh$/) { $retval .= '.SH'; if ($words[0] eq 'SYNOPSIS') { $synopsis = 1; } else { $synopsis = 0; } next; } if (/^Xr$/) { $retval .= '\\fB' . (shift @words) . '\\fP(' . (shift @words) . ')' . (shift @words); last; } if (/^Rs/) { @refauthors = (); $reftitle = ''; $refissue = ''; $refdate = ''; $refopt = ''; $reference = 1; last; } if (/^Re/) { $retval .= "\n"; # authors while (scalar(@refauthors) > 1) { $retval .= shift(@refauthors) . ', '; } $retval .= 'and ' if ($retval ne ''); $retval .= shift(@refauthors); # title $retval .= ', \\fI' . $reftitle . '\\fP'; # issue $retval .= ', ' . $refissue if ($refissue ne ''); # date $retval .= ', ' . $refdate if ($refdate ne ''); # optional info $retval .= ', ' . $refopt if ($refopt ne ''); $retval .= ".\n"; $reference = 0; last; } if ($reference) { if (/^%A$/) { unshift(@refauthors, join(' ', @words)); last; } if (/^%T$/) { $reftitle = join(' ', @words); $reftitle =~ s/^"//; $reftitle =~ s/"$//; last; } if (/^%N$/) { $refissue = join(' ', @words); last; } if (/^%D$/) { $refdate = join(' ', @words); last; } if (/^%O$/) { $refopt = join(' ', @words); last; } } if (/^Nm$/) { my $n = $name; $n = shift @words if (@words > 0); $name = $n unless $name; $retval .= ".br\n" if ($synopsis); $retval .= "\\fB$n\\fP"; $nospace = 1 if (! $nospace && $words[0] =~ m/^[\.,]/); next; } if (/^Nd$/) { $retval .= '\\-'; next; } if (/^Fl$/) { $retval .= '\\fB\\-' . (shift @words) . '\\fP'; $nospace = 1 if (! $nospace && $words[0] =~ m/^[\.,]/); next; } if (/^Ar$/) { $retval .= '\\fI'; if (! defined $words[0]) { $retval .= 'file ...\\fP'; } else { $retval .= shift(@words) . '\\fP'; while ($words[0] eq '|') { $retval .= ' ' . shift(@words); $retval .= ' \\fI' . shift(@words); $retval .= '\\fP'; } } $nospace = 1 if (! $nospace && $words[0] =~ m/^[\.,]/); next; } if (/^Cm$/) { $retval .= '\\fB' . (shift @words) . '\\fP'; while ($words[0] =~ m/^[\.,:)]$/) { $retval .= shift(@words); } next; } if (/^Op$/) { $option = 1; $nospace = 1 if (! $nospace); $retval .= '['; # my $tmp = pop(@words); # $tmp .= ']'; # push(@words, $tmp); next; } if (/^Pp$/) { $retval .= "\n"; next; } if (/^Ss$/) { $retval .= '.SS'; next; } if (/^Pa$/ && ! $option) { $retval .= '\\fI'; $retval .= '\\&' if ($words[0] =~ m/^\./); $retval .= (shift @words) . '\\fP'; while ($words[0] =~ m/^[\.,:;)]$/) { $retval .= shift(@words); } # $nospace = 1 # if (! $nospace && $words[0] =~ m/^[\.,:)]/); next; } if (/^Dv$/) { $retval .= '.BR'; next; } if (/^(Em|Ev)$/) { $retval .= '.IR'; next; } if (/^Pq$/) { $retval .= '('; $nospace = 1; $parens = 1; next; } if (/^(S[xy])$/) { $retval .= '.B ' . join(' ', @words); last; } if (/^Ic$/) { $retval .= '\\fB'; while (defined $words[0] && $words[0] !~ m/^[\.,]/) { if ($words[0] eq 'Op') { shift(@words); $retval .= '['; my $tmp = pop(@words); $tmp .= ']'; push(@words, $tmp); next; } if ($words[0] eq 'Ar') { shift @words; $retval .= '\\fI'; $retval .= shift @words; $retval .= '\\fP'; } else { $retval .= shift @words; } $retval .= ' ' if (! $nospace); } $retval =~ s/ $//; $retval .= '\\fP'; $retval .= shift @words if (defined $words[0]); last; } if (/^Bl$/) { $oldoptlist = $optlist; if ($words[0] eq '-bullet') { $optlist = 1; } elsif ($words[0] eq '-enum') { $optlist = 2; $enum = 0; } elsif ($words[0] eq '-tag') { $optlist = 3; } elsif ($words[0] eq '-item') { $optlist = 4; } last; } if (/^El$/) { $optlist = $oldoptlist; next; } if ($optlist && /^It$/) { if ($optlist == 1) { # bullets $retval .= '.IP \\(bu'; next; } if ($optlist == 2) { # enum $retval .= '.IP ' . (++$enum) . '.'; next; } if ($optlist == 3) { # tags $retval .= ".TP\n"; if ($words[0] =~ m/^(Pa|Ev)$/) { shift @words; $retval .= '.B'; } next; } if ($optlist == 4) { # item $retval .= ".IP\n"; next; } next; } if (/^Sm$/) { if ($words[0] eq 'off') { $nospace = 2; } elsif ($words[0] eq 'on') { # $retval .= "\n"; $nospace = 0; } shift @words; next; } $retval .= "$_"; } return undef if ($retval eq '.'); $retval =~ s/^\.([^a-zA-Z])/$1/; # $retval =~ s/ $//; $retval .= ')' if ($parens == 1); $retval .= ']' if ($option == 1); # $retval .= ' ' # if ($nospace && $retval ne '' && $retval !~ m/\n$/); # $retval .= ' ' # if ($extended && $retval !~ m/ $/); $retval .= ' ' if ($ext && ! $extopt && $retval !~ m/ $/); $retval .= "\n" if (! $ext && ! $extopt && $retval ne '' && $retval !~ m/\n$/); return $retval; }