mdoc2man revision 285612
1144518Sdavidxu#! /usr/local/bin/perl 2144518Sdavidxu 3144518Sdavidxu## mdoc2man.pl -- Convert mdoc tags to man tags 4144518Sdavidxu## 5144518Sdavidxu## Author: Harlan Stenn <stenn@ntp.org> 6144518Sdavidxu## 7144518Sdavidxu## 8144518Sdavidxu## This file is part of AutoOpts, a companion to AutoGen. 9144518Sdavidxu## AutoOpts is free software. 10144518Sdavidxu## AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved 11144518Sdavidxu## 12144518Sdavidxu## AutoOpts is available under any one of two licenses. The license 13144518Sdavidxu## in use must be one of these two and the choice is under the control 14144518Sdavidxu## of the user of the license. 15144518Sdavidxu## 16144518Sdavidxu## The GNU Lesser General Public License, version 3 or later 17144518Sdavidxu## See the files "COPYING.lgplv3" and "COPYING.gplv3" 18144518Sdavidxu## 19144518Sdavidxu## The Modified Berkeley Software Distribution License 20144518Sdavidxu## See the file "COPYING.mbsd" 21144518Sdavidxu## 22144518Sdavidxu## These files have the following sha256 sums: 23144518Sdavidxu## 24144518Sdavidxu## 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3 25144518Sdavidxu## 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3 26144518Sdavidxu## 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd 27144518Sdavidxu 28144518Sdavidxu### ToDo 29144518Sdavidxu# Properly implement -columns in the "my %lists" definition... 30144518Sdavidxu# 31144518Sdavidxu# .Xr requires at least 1 arg, the code here expects at least 2 32144518Sdavidxu# 33144518Sdavidxu### 34144518Sdavidxu 35144518Sdavidxupackage mdoc2man; 36144518Sdavidxuuse strict; 37144518Sdavidxuuse warnings; 38144518Sdavidxuuse File::Basename; 39144518Sdavidxuuse lib dirname(__FILE__); 40144518Sdavidxuuse Mdoc qw(hs ns pp mapwords son soff stoggle gen_encloser); 41144518Sdavidxu 42165967Simp######## 43144518Sdavidxu## Basic 44144518Sdavidxu######## 45144518Sdavidxu 46144518SdavidxuMdoc::def_macro( '.Sh', sub { '.SH', hs, @_ }, raw => 1); 47144518SdavidxuMdoc::def_macro( '.Ss', sub { '.SS', hs, @_ }, raw => 1); 48144518SdavidxuMdoc::def_macro( '.Pp', sub { ".sp \\n(Ppu\n.ne 2\n" } ); 49144518SdavidxuMdoc::def_macro( '.Nd', sub { "\\- @_" } ); 50144518Sdavidxu 51144518Sdavidxu# Macros that enclose things 52144518SdavidxuMdoc::def_macro( '.Brq', gen_encloser(qw({ })) , greedy => 1 ); 53144518SdavidxuMdoc::def_macro( '.Op' , gen_encloser(qw([ ])) , greedy => 1 ); 54144518SdavidxuMdoc::def_macro( '.Qq' , gen_encloser(qw(" ")) , greedy => 1 ); 55144518SdavidxuMdoc::def_macro( '.Dq' , gen_encloser(qw(\*[Lq] \*[Rq])), greedy => 1 ); 56144518SdavidxuMdoc::def_macro( '.Ql' , gen_encloser(qw(\[oq] \[cq])) , greedy => 1 ); 57144518SdavidxuMdoc::def_macro( '.Sq' , gen_encloser(qw(\[oq] \[cq])) , greedy => 1 ); 58144518SdavidxuMdoc::def_macro( '.Pq' , gen_encloser(qw/( )/) , greedy => 1 ); 59144518SdavidxuMdoc::def_macro( '.D1' , sub { ".in +4\n", ns, @_ , ns , "\n.in -4" } , greedy => 1); 60267200Skib 61157457SdavidxuMdoc::def_macro( 'Oo', sub { '[', @_ } ); 62144518SdavidxuMdoc::def_macro( 'Oc', sub { ']', @_ } ); 63211706Skib 64144518SdavidxuMdoc::def_macro( 'Po', sub { '(', @_} ); 65144518SdavidxuMdoc::def_macro( 'Pc', sub { ')', @_ } ); 66144518Sdavidxu 67144518SdavidxuMdoc::def_macro( 'Bro', sub { '{', ns, @_ } ); 68144518SdavidxuMdoc::def_macro( 'Brc', sub { '}', @_ } ); 69157457Sdavidxu 70144518SdavidxuMdoc::def_macro( '.Oo', gen_encloser(qw([ ])), concat_until => '.Oc' ); 71144518SdavidxuMdoc::def_macro( '.Bro', gen_encloser(qw({ })), concat_until => '.Brc' ); 72185369SkibMdoc::def_macro( '.Po', gen_encloser(qw/( )/), concat_until => '.Pc' ); 73144518Sdavidxu 74144518SdavidxuMdoc::def_macro( '.Ev', sub { @_ } ); 75144518SdavidxuMdoc::def_macro( '.An', sub { ".NOP ", @_, "\n.br" }, raw => 1 ); 76144518SdavidxuMdoc::def_macro( '.Li', sub { mapwords {"\\f[C]$_\\f[]"} @_ } ); 77144518SdavidxuMdoc::def_macro( '.Cm', sub { mapwords {"\\f\\*[B-Font]$_\\f[]"} @_ } ); 78144518SdavidxuMdoc::def_macro( '.Ic', sub { mapwords {"\\f\\*[B-Font]$_\\f[]"} @_ } ); 79144518SdavidxuMdoc::def_macro( '.Fl', sub { mapwords {"\\f\\*[B-Font]\\-$_\\f[]"} @_ } ); 80144518SdavidxuMdoc::def_macro( '.Ar', sub { mapwords {"\\f\\*[I-Font]$_\\f[]"} @_ } ); 81144518SdavidxuMdoc::def_macro( '.Em', sub { mapwords {"\\fI$_\\f[]"} @_ } ); 82144518SdavidxuMdoc::def_macro( '.Va', sub { mapwords {"\\fI$_\\f[]"} @_ } ); 83144518SdavidxuMdoc::def_macro( '.Sx', sub { mapwords {"\\fI$_\\f[]"} @_ } ); 84144518SdavidxuMdoc::def_macro( '.Xr', sub { "\\fC".(shift)."\\f[]\\fR(".(shift).")\\f[]", @_ } ); 85144518SdavidxuMdoc::def_macro( '.Fn', sub { "\\f\\*[B-Font]".(shift)."\\f[]\\fR()\\f[]" } ); 86144518SdavidxuMdoc::def_macro( '.Fn', sub { "\\fB".(shift)."\\f[]\\fR()\\f[]" } ); 87144518SdavidxuMdoc::def_macro( '.Fx', sub { "FreeBSD", @_ } ); 88144518SdavidxuMdoc::def_macro( '.Ux', sub { "UNIX", @_ } ); 89144518Sdavidxu 90144518SdavidxuMdoc::def_macro( '.No', sub { ".NOP", map { ($_, ns) } @_ } ); 91144518SdavidxuMdoc::def_macro( '.Pa', sub { mapwords {"\\fI$_\\f[]"} @_; } ); 92144518Sdavidxu{ 93212078Sdavidxu my $name; 94212078Sdavidxu Mdoc::def_macro('.Nm', sub { 95144518Sdavidxu $name = shift if (!$name); 96212077Sdavidxu "\\f\\*[B-Font]$name\\fP", @_ 97212078Sdavidxu } ); 98144518Sdavidxu} 99144518Sdavidxu 100144518Sdavidxu######## 101211706Skib## lists 102211706Skib######## 103211706Skib 104212083Sdavidxumy %lists = ( 105211706Skib bullet => sub { 106211706Skib Mdoc::def_macro('.It', sub { '.IP \fB\(bu\fP 2' }); 107211706Skib }, 108211706Skib 109211706Skib column => sub { 110211706Skib Mdoc::def_macro('.It', sub { '.IP \fB\(bu\fP 2' }); 111212083Sdavidxu }, 112212077Sdavidxu 113211706Skib tag => sub { 114211706Skib my (%opts) = @_; 115211706Skib 116211706Skib my $width = ''; 117211706Skib 118212083Sdavidxu if (exists $opts{width}) { 119211706Skib $width = ' '.((length $opts{width})+1); 120211706Skib } 121212077Sdavidxu 122212083Sdavidxu if (exists $opts{compact}) { 123212083Sdavidxu my $dobrns = 0; 124212083Sdavidxu Mdoc::def_macro('.It', sub { 125212083Sdavidxu my @ret = (".TP$width\n.NOP", hs); 126212083Sdavidxu if ($dobrns) { 127211860Sdavidxu ".br\n.ns\n", ns, @ret, @_; 128212076Sdavidxu } 129211706Skib else { 130211706Skib $dobrns = 1; 131277317Skib @ret, @_; 132144518Sdavidxu } 133144518Sdavidxu }, raw => 1); 134277317Skib } 135144518Sdavidxu else { 136144518Sdavidxu Mdoc::def_macro('.It', sub { 137144518Sdavidxu ".TP$width\n.NOP", hs, @_ 138144518Sdavidxu }, raw => 1); 139212841Sdavidxu } 140191993Sgreen }, 141185558Skib); 142144518Sdavidxu 143144518SdavidxuMdoc::set_Bl_callback(do { my $nested = 0; sub { 144144518Sdavidxu my $type = shift; 145144518Sdavidxu my %opts = Mdoc::parse_opts(@_); 146144518Sdavidxu if (defined $type && $type =~ /-(\w+)/ && exists $lists{$1}) { 147212841Sdavidxu 148212841Sdavidxu # Wrap nested lists with .RS and .RE 149212077Sdavidxu Mdoc::set_El_callback(sub { 150144518Sdavidxu return '.RE' if $nested-- > 1; 151144518Sdavidxu return '.PP'; 152144518Sdavidxu }); 153144518Sdavidxu 154144518Sdavidxu $lists{$1}->(%opts); 155144518Sdavidxu 156144518Sdavidxu if ($nested++) { 157144518Sdavidxu return ".RS"; 158212077Sdavidxu } 159212077Sdavidxu else { 160212077Sdavidxu return (); 161212077Sdavidxu } 162212077Sdavidxu } 163212077Sdavidxu else { 164191993Sgreen die "Invalid list type <$type>"; 165191993Sgreen } 166191993Sgreen}}, raw => 1); 167144518Sdavidxu 168154248Sjasone# don't bother with arguments for now and do what mdoc2man'.sh' did 169191993Sgreen 170154248SjasoneMdoc::def_macro('.Bd', sub { ".br\n.in +4\n.nf" } ); 171185369SkibMdoc::def_macro('.Ed', sub { ".in -4\n.fi" } ); 172144518Sdavidxu 173191993SgreenMdoc::set_Re_callback(sub { 174144518Sdavidxu my ($reference) = @_; 175144518Sdavidxu <<"REF"; 176267200Skib$reference->{authors}, 177267200Skib\\fI$reference->{title}\\fR, 178267200Skib$reference->{optional}\n.PP 179267200SkibREF 180267200Skib}); 181267200Skib 182267200Skib# Define all macros which have the same sub for inline and standalone macro 183267200Skibfor (qw(Xr Em Ar Fl Ic Cm Qq Op Nm Pa Sq Li Va Brq Pq Fx Ux)) { 184267200Skib my $m = Mdoc::get_macro(".$_"); 185144518Sdavidxu Mdoc::def_macro($_, delete $m->{run}, %$m); 186144518Sdavidxu} 187164583Sdavidxu 188212536Sdavidxusub print_line { 189163346Sdavidxu print shift; 190144518Sdavidxu print "\n"; 191144518Sdavidxu} 192144518Sdavidxu 193144518Sdavidxusub run { 194212536Sdavidxu print <<'DEFS'; 195144518Sdavidxu.de1 NOP 196144518Sdavidxu. it 1 an-trap 197144518Sdavidxu. if \\n[.$] \,\\$*\/ 198144518Sdavidxu.. 199144518Sdavidxu.ie t \ 200162061Sdavidxu.ds B-Font [CB] 201212077Sdavidxu.ds I-Font [CI] 202185531Skan.ds R-Font [CR] 203212076Sdavidxu.el \ 204212076Sdavidxu.ds B-Font B 205191993Sgreen.ds I-Font I 206185531Skan.ds R-Font R 207144518SdavidxuDEFS 208144518Sdavidxu 209144518Sdavidxu while (my ($macro, @args) = Mdoc::parse_line(\*STDIN, \&print_line)) { 210144518Sdavidxu my @ret = Mdoc::call_macro($macro, @args); 211144518Sdavidxu print_line(Mdoc::to_string(@ret)) if @ret; 212212077Sdavidxu } 213212077Sdavidxu return 0; 214144518Sdavidxu} 215191993Sgreen 216190025Skibexit run(@ARGV) unless caller; 217185456Skib 218190025Skib1; 219190025Skib__END__ 220185369Skib