#! /usr/bin/perl # # Does a first approximation of converting a BSD man page into something # suitable for GNO. Note that you still have to review the output of # this filter -- no everything is handled, nor is everything handled # correctly. # # $Id: bsd2man,v 1.2 1997/10/30 04:21:56 gdr Exp $ # # Devin Reade, December 1996 # $last_nm = ''; # previously used function name $title_printed = 0; # has the title line been printed? $chapterNames{'0'} = 'General Information'; $chapterNames{'1'} = 'Commands and Applications'; $chapterNames{'2'} = 'System Calls'; $chapterNames{'3'} = 'Library Routines'; $chapterNames{'4'} = 'Devices'; $chapterNames{'5'} = 'File Formats'; $chapterNames{'6'} = 'Games'; $chapterNames{'7'} = 'Miscellaneous'; $chapterNames{'8'} = 'System Administration'; $chapterNames{'L'} = 'Local'; $chapterNames{'N'} = 'New'; $authorCount = 0; while (<>) { chop; study; # ignore the following (no change in behavior) # .sp # .I if (/^.%A\s+(.*)$/) { # authors $line = $1; $line =~ s/\s+$//; $authors[$authorCount++] = $line; next; } else { if ($authorCount > 0) { printf("by\n"); for ($i=0; $i<$authorCount-1; $i++) { printf("%s,\n", $authors[$i]); } printf("%s.\n", $authors[$authorCount-1]); $authorCount = 0; } } if (/^\.It\s+Bq\s+Er\s+(.*)$/) { # list item $line = $1; $line =~ s/\s+$//; printf(".IP \\fB%s\\fR\n", $line); } elsif (/^\.(RI|PP|SH|sp|ft|I|nf|fi|br|TH|\\\"|if)/) { # pass through verbatim printf("%s\n", $_); } elsif (/^\.(Ar|Dv|El|Pp|Re|Rs|Sh|Va|%B|%T)/) { # simple replacement $oldval = $1; ($oldval eq 'Ar') && (s/$oldval/BR/); # argument ($oldval eq 'Dv') && (s/$oldval/BR/); # macro value (approx) ($oldval eq 'El') && (s/$oldval/RE/); # end list ($oldval eq 'Pp') && (s/$oldval/LP/); # paragraph ($oldval eq 'Re') && (s/$oldval/RE/); # relative indent end ($oldval eq 'Rs') && (s/$oldval/RS/); # relative indent start ($oldval eq 'Va') && (s/$oldval/IR/); # variable ($oldval eq '%B') && (s/$oldval/B/); # programmer's sup docs ($oldval eq '%T') && (s/$oldval/I/); # title if ($oldval eq 'Sh') { # section header if ($title_printed == 0) { $title_printed++; printf(".TH %s %s %s %s \"%s\"\n", $pagename, $chapter, $date, $os, defined($chapterNames{$chapter}) ? $chapterNames{$chapter} : '(unlisted chapter)'); } s/$oldval/SH/; } printf("%s\n", $_); } elsif (/^\.Xr\s+(\S+)\s*(.*)$/) { # cross reference $xref = $1; $rest = $2; if ($rest =~ /^\d+/) { $section = int($&); $rest = $'; } else { $section = -1; } $rest =~ s/\s+//g; if ($section == -1) { printf(".BR %s %s\n", $xref, $rest); } else { printf(".BR %s (%s)%s\n", $xref, $section, $rest); } } elsif (/^\.(Nm)\s*$/) { # missing referent $oldval = $1; ($oldval eq 'Nm') && printf(".BR %s\n", $last_nm); } elsif (/^\.(Nm)\s+([\"\'][^\"\']*[\"\'])\s*(.*)$/) { # quoted first argument $oldval = $1; $first = $2; $rest = $3; if ($oldval eq 'Nm') { $last_nm = $first; $oldval = 'BR'; } if (($rest =~ /\s/) && !($rest =~ /[\"\']/)) { printf(".%s %s \"%s\"\n", $oldval, $first, $rest); } else { printf(".%s %s %s\n", $oldval, $first, $rest); } } elsif (/^\.(Nm)\s+(\S+)\s*(.*)$/) { # unquoted first argument $oldval = $1; $first = $2; $rest = $3; if ($oldval eq 'Nm') { $last_nm = $first; s/$oldval/BR/; } printf ("%s\n", $_); } elsif (/^\.Fd\s+(.*)$/) { # function define (?) printf(".br\n%s\n", $1); } elsif (/^\.Ft\s+(.*)$/) { # function type printf(".sp 1\n%s\n", $1); } elsif (/^\.Fn\s+(\S+)\s*(.*)$/) { # function name, perhaps with protos $n = $1; $rest = $2; if ($rest =~ /[\"\']/) { $rest =~ s/^\s*[\"\']/\(/; $rest =~ s/\"\s+\"/, /g; $rest =~ s/[\"\']\s*$/\);/; printf ("%s %s\n", $n, $rest); } else { printf (".BR %s %s\n", $n, $rest); } } elsif (/^\.Fa\s+(.*)$/) { # function argument $line = $1; $line =~ s/\s+$//; if (($line =~ /^\S+$/) || ($line =~ /[\"\']([^\"\']+)[\"\']/)) { printf(".I %s\n", $line); } elsif ($line =~ /\(?(\S+)\)?/) { printf(".RI ( %s )\n", $1); } else { printf(".IR %s\n", $line); } } elsif (/^\.Em/) { @line = split; shift @line; $line = ''; $firstword = ''; $word = shift @line; if ($word =~ /([\'\"])/) { # get the emphasized part $quote = $1; $firstword .= $word; do { $word = shift @line; $firstword .= ' ' . $word; } while (($word ne '') && !($word =~ /$quote/)); } else { $firstword .= $word; } $skip_space = 1; $quote = '"'; foreach $w (@line) { ($quote eq '"') && ($line .= ' '.$quote) && ($quote = ''); ($w eq 'Ns') && ($skip_space = 1) && next; ($w eq 'Ap') && ($skip_space = 1) && ($line .= "'") && next; if ($skip_space == 1) { $line .= $w; $skip_space = 0; } else { $line .= ' ' . $w; } } ($quote eq '') && ($line .= '"'); if ($line =~ /^\s*"(\S+)"\s*$/) { # dump unecessary quotes $line = $1; } printf(".IR %s %s\n", $firstword, $line); } elsif (/^\.Dd\s+[\"\']?([^\"\']+)[\"\']?/) { # date $date = '"' . $1 . '"'; } elsif (/^\.Os\s+(.*)$/) { # specified operating system $os = $1; $os =~ s/\s+$//; $os =~ s/[\"\']//g; if (! $os =~ /\d+\.\d+/) { $os =~ s/BSD\s+/BSD 4./; } $os = '"' . $os . '"'; } elsif (/^\.Os\s*$/) { # unspecified operating system $os = '""'; } elsif (/^\.Dt\s+(.*)\s+(\d+[\S]*)\s*$/) { # name and section number $pagename = $1; $chapter = $2; $chapter =~ /(\d+)/; $chapternumber = $&; if (($pagename =~ /\s/) && !($pagename =~ /[\"\']/)) { $pagename = '"' . $pagename . '"'; } } elsif (/^\.Nd\s+[\"\']?([^\"\']+)[\"\']?/) { # brief description printf ("\\- %s\n", $1); } elsif (/^\.Bx\s+(\d+\.\d+)(.*)$/) { # BSD version s/^\.Bx/BSD/; s/\s+Reno\s+/ \(Reno\) /g; s/\s+\.\s*$/./; printf("%s\n", $_); } elsif (/^\.Bl\s+/) { # begin list printf(".RS\n"); } elsif (/^(\.%N)/) { # volume number. See .%B above. s/$1/volume/; printf("%s\n", $_); } elsif (/^\./) { # catch unrecognised commands printf(STDERR "Unknown command line %d: %s\n", $., $_); printf("%s\n", $_); } else { # normal line printf("%s\n", $_); } }