blob: 719e1e0c92ccb97db83db3562ccafb2cdfcaae2d [file] [log] [blame]
#!/usr/bin/perl
###
### Quick usage: mdoc2man.pl < mdoc_manpage.8 > doc_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, $nospace, $enum, $synopsis);
$optlist = 0; ### 1 = bullet, 2 = enum, 3 = tag
$nospace = 0;
$synopsis = 0;
while ($line = <STDIN>)
{
if ($line !~ /^\./)
{
print $line;
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, $arg);
@words = split(/\s+/, $line);
$retval = '';
$option = 0;
$parens = 0;
$arg = 0;
# print('@words = ', scalar(@words), ': ', join(' ', @words), "\n");
while ($_ = shift @words)
{
# print "WORD: $_\n";
next
if (/^(Li|Pf|X[oc])$/);
if (/^Ns/)
{
$nospace = 1
if (! $nospace);
$retval =~ s/ $//;
next;
}
if (/^No/)
{
$retval =~ s/ $//;
$retval .= shift @words;
next;
}
if (/^Dq$/) {
$retval .= '``' . (shift @words) . '\'\'';
$nospace = 1
if (! $nospace && $words[0] =~ m/^[\.,]/);
next;
}
if (/^(Sq|Ql)$/) {
$retval .= '`' . (shift @words) . '\'';
$nospace = 1
if (! $nospace && $words[0] =~ m/^[\.,]/);
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) .
'\\fR(' . (shift @words) . ')'
. (shift @words);
last;
}
if (/^Nm$/) {
$name = shift @words
if (@words > 0);
$retval .= ".br\n"
if ($synopsis);
$retval .= "\\fB$name\\fR";
$nospace = 1
if (! $nospace && $words[0] =~ m/^[\.,]/);
next;
}
if (/^Nd$/) {
$retval .= '\\-';
next;
}
if (/^Fl$/) {
$retval .= '\\fB\\-' . (shift @words) . '\\fR';
$nospace = 1
if (! $nospace && $words[0] =~ m/^[\.,]/);
next;
}
if (/^Ar$/) {
$retval .= '\\fI';
if (! defined $words[0])
{
$retval .= 'file ...\\fR';
}
$arg = 1;
$nospace = 1
if (! $nospace);
next;
}
if (/^Cm$/) {
$retval .= '\\fB' . (shift @words) . '\\fR';
next;
}
if (/^Op$/) {
$option = 1;
$nospace = 1
if (! $nospace);
$retval .= '[';
next;
}
if (/^Oo$/) {
$retval .= "[\\c\n";
next;
}
if (/^Oc$/) {
$retval .= ']';
next;
}
if (/^Pp$/) {
if ($optlist) {
$retval .= "\n";
} else {
$retval .= '.LP';
}
next;
}
if (/^Ss$/) {
$retval .= '.SS';
next;
}
if (/^Pa$/ && ! $option) {
$retval .= '\\fI';
$retval .= '\\&'
if ($words[0] =~ m/^\./);
$retval .= (shift @words) . '\\fR';
$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/^[\.,]/)
{
$retval .= shift @words;
$retval .= ' '
if (! $nospace);
}
$retval =~ s/ $//;
$retval .= '\\fR';
$retval .= shift @words
if (defined $words[0]);
last;
}
if (/^Bl$/) {
if ($words[0] eq '-bullet') {
$optlist = 1;
} elsif ($words[0] eq '-enum') {
$optlist = 2;
$enum = 0;
} elsif ($words[0] eq '-tag') {
$optlist = 3;
}
last;
}
if (/^El$/) {
$optlist = 0;
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;
}
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 .= '\\fR'
if ($arg);
$retval .= '\\c'
if ($nospace && $retval ne '' && $retval !~ m/\n$/);
$retval .= "\n"
if ($retval ne '' && $retval !~ m/\n$/);
return $retval;
}