1290001Sglebius#! /usr/bin/perl 2290001Sglebius 3290001Sglebius### To Do: 4290001Sglebius 5290001Sglebius# the Bl -column command needs work: 6290001Sglebius# - support for "-offset" 7290001Sglebius# - support for the header widths 8290001Sglebius 9290001Sglebius# 10290001Sglebius 11290001Sglebius### 12290001Sglebius 13290001Sglebiuspackage mdoc2texi; 14290001Sglebiususe strict; 15290001Sglebiususe warnings; 16290001Sglebiususe File::Basename qw(dirname); 17290001Sglebiususe lib dirname(__FILE__); 18290001Sglebiususe Mdoc qw(ns pp hs mapwords gen_encloser nl); 19290001Sglebius 20290001Sglebius# Ignore commments 21290001SglebiusMdoc::def_macro( '.\"', sub { () } ); 22290001Sglebius 23290001Sglebius# Enclosers 24290001SglebiusMdoc::def_macro( '.An', sub { @_, ns, '@*' } ); 25290001SglebiusMdoc::def_macro( '.Aq', gen_encloser(qw(< >)), greedy => 1); 26290001SglebiusMdoc::def_macro( '.Bq', gen_encloser(qw([ ])), greedy => 1); 27290001SglebiusMdoc::def_macro( '.Brq', gen_encloser(qw(@{ @})), greedy => 1); 28290001SglebiusMdoc::def_macro( '.Pq', gen_encloser(qw/( )/), greedy => 1); 29290001SglebiusMdoc::def_macro( '.Qq', gen_encloser(qw(" ")), greedy => 1); 30290001SglebiusMdoc::def_macro( '.Op', gen_encloser(qw(@code{[ ]})), greedy => 1); 31290001SglebiusMdoc::def_macro( '.Ql', gen_encloser(qw(@quoteleft{} @quoteright{})), 32290001Sglebius greedy => 1); 33290001SglebiusMdoc::def_macro( '.Sq', gen_encloser(qw(@quoteleft{} @quoteright{})), 34290001Sglebius greedy => 1); 35290001SglebiusMdoc::def_macro( '.Dq', gen_encloser(qw(@quotedblleft{} @quotedblright{})), 36290001Sglebius greedy => 1); 37290001SglebiusMdoc::def_macro( '.Eq', sub { 38290001Sglebius my ($o, $c) = (shift, pop); 39290001Sglebius gen_encloser($o, $c)->(@_) 40290001Sglebius}, greedy => 1); 41290001SglebiusMdoc::def_macro( '.D1', sub { "\@example\n", ns, @_, ns, "\n\@end example" }, 42290001Sglebius greedy => 1); 43290001SglebiusMdoc::def_macro( '.Dl', sub { "\@example\n", ns, @_, ns, "\n\@end example" }, 44290001Sglebius greedy => 1); 45290001Sglebius 46290001SglebiusMdoc::def_macro( '.Oo', gen_encloser(qw(@code{[ ]})), concat_until => '.Oc'); 47290001SglebiusMdoc::def_macro( 'Oo', sub { '@code{[', ns, @_ } ); 48290001SglebiusMdoc::def_macro( 'Oc', sub { @_, ns, pp(']}') } ); 49290001Sglebius 50290001SglebiusMdoc::def_macro( '.Bro', gen_encloser(qw(@code{@{ @}})), concat_until => '.Brc'); 51290001SglebiusMdoc::def_macro( 'Bro', sub { '@code{@{', ns, @_ } ); 52290001SglebiusMdoc::def_macro( 'Brc', sub { @_, ns, pp('@}}') } ); 53290001Sglebius 54290001SglebiusMdoc::def_macro( '.Po', gen_encloser(qw/( )/), concat_until => '.Pc'); 55290001SglebiusMdoc::def_macro( 'Po', sub { '(', @_ } ); 56290001SglebiusMdoc::def_macro( 'Pc', sub { @_, ')' } ); 57290001Sglebius 58290001SglebiusMdoc::def_macro( '.Ar', sub { mapwords {"\@kbd{$_}"} @_ } ); 59290001SglebiusMdoc::def_macro( '.Fl', sub { mapwords {"\@code{-$_}"} @_ } ); 60290001SglebiusMdoc::def_macro( '.Cm', sub { mapwords {"\@code{-$_}"} @_ } ); 61290001SglebiusMdoc::def_macro( '.Ic', sub { mapwords {"\@code{$_}"} @_ } ); 62290001SglebiusMdoc::def_macro( '.Cm', sub { mapwords {"\@code{$_}"} @_ } ); 63290001SglebiusMdoc::def_macro( '.Li', sub { mapwords {"\@code{$_}"} @_ } ); 64290001SglebiusMdoc::def_macro( '.Va', sub { mapwords {"\@code{$_}"} @_ } ); 65290001SglebiusMdoc::def_macro( '.Em', sub { mapwords {"\@emph{$_}"} @_ } ); 66290001SglebiusMdoc::def_macro( '.Fn', sub { '@code{'.(shift).'()}' } ); 67290001SglebiusMdoc::def_macro( '.Ss', sub { "\@subsubsection", hs, @_ }); 68290001SglebiusMdoc::def_macro( '.Sh', sub { 69290001Sglebius my $name = "@_"; 70290001Sglebius "\@node", hs, "$name\n", ns, "\@subsection", hs, $name 71290001Sglebius }); 72290001SglebiusMdoc::def_macro( '.Ss', sub { "\@subsubsection", hs, @_ }); 73290001SglebiusMdoc::def_macro( '.Xr', sub { '@code{'.(shift).'('.(shift).')}', @_ } ); 74290001SglebiusMdoc::def_macro( '.Sx', gen_encloser(qw(@ref{ })) ); 75290001SglebiusMdoc::def_macro( '.Ux', sub { '@sc{unix}', @_ } ); 76290001SglebiusMdoc::def_macro( '.Fx', sub { '@sc{freebsd}', @_ } ); 77290001Sglebius{ 78290001Sglebius my $name; 79290001Sglebius Mdoc::def_macro('.Nm', sub { 80290001Sglebius $name = shift || $ENV{AG_DEF_PROG_NAME} || 'XXX' if (!$name); 81290001Sglebius "\@code{$name}" 82290001Sglebius } ); 83290001Sglebius} 84290001SglebiusMdoc::def_macro( '.Pa', sub { mapwords {"\@file{$_}"} @_ } ); 85290001SglebiusMdoc::def_macro( '.Pp', sub { '' } ); 86290001Sglebius 87290001Sglebius# Setup references 88290001Sglebius 89290001SglebiusMdoc::def_macro( '.Rs', sub { "\@*\n", @_ } ); 90290001SglebiusMdoc::set_Re_callback(sub { 91290001Sglebius my ($reference) = @_; 92290001Sglebius "@*\n", ns, $reference->{authors}, ',', "\@emph{$reference->{title}}", 93290001Sglebius ',', $reference->{optional} 94290001Sglebius }); 95290001Sglebius 96290001Sglebius# Set up Bd/Ed 97290001Sglebius 98290001Sglebiusmy %displays = ( 99290001Sglebius literal => [ '@verbatim', '@end verbatim' ], 100290001Sglebius); 101290001Sglebius 102290001SglebiusMdoc::def_macro( '.Bd', sub { 103290001Sglebius (my $type = shift) =~ s/^-//; 104290001Sglebius die "Not supported display type <$type>" 105290001Sglebius if not exists $displays{ $type }; 106290001Sglebius 107290001Sglebius my $orig_ed = Mdoc::get_macro('.Ed'); 108290001Sglebius Mdoc::def_macro('.Ed', sub { 109290001Sglebius Mdoc::def_macro('.Ed', delete $orig_ed->{run}, %$orig_ed); 110290001Sglebius $displays{ $type }[1]; 111290001Sglebius }); 112290001Sglebius $displays{ $type }[0] 113290001Sglebius }); 114290001SglebiusMdoc::def_macro('.Ed', sub { die '.Ed used but .Bd was not seen' }); 115290001Sglebius 116290001Sglebius# Set up Bl/El 117290001Sglebius 118290001Sglebiusmy %lists = ( 119290001Sglebius bullet => [ '@itemize @bullet', '@end itemize' ], 120290001Sglebius tag => [ '@table @asis', '@end table' ], 121290001Sglebius column => [ '@table @asis', '@end table' ], 122290001Sglebius); 123290001Sglebius 124290001SglebiusMdoc::set_Bl_callback(sub { 125290001Sglebius my $type = shift; 126290001Sglebius die "Specify a list type" if not defined $type; 127290001Sglebius $type =~ s/^-//; 128290001Sglebius die "Not supported list type <$type>" if not exists $lists{ $type }; 129290001Sglebius Mdoc::set_El_callback(sub { $lists{ $type }[1] }); 130290001Sglebius $lists{ $type }[0] 131290001Sglebius }); 132290001SglebiusMdoc::def_macro('.It', sub { '@item', hs, @_ }); 133290001Sglebius 134290001Sglebiusfor (qw(Aq Bq Brq Pq Qq Ql Sq Dq Eq Ar Fl Ic Pa Op Cm Li Fx Ux Va)) { 135290001Sglebius my $m = Mdoc::get_macro(".$_"); 136290001Sglebius Mdoc::def_macro($_, delete $m->{run}, %$m); 137290001Sglebius} 138290001Sglebius 139290001Sglebiussub print_line { 140290001Sglebius my $s = shift; 141290001Sglebius $s =~ s/\\&//g; 142290001Sglebius print "$s\n"; 143290001Sglebius} 144290001Sglebius 145290001Sglebiussub preprocess_args { 146290001Sglebius $_ =~ s/([{}])/\@$1/g for @_; 147290001Sglebius} 148290001Sglebius 149290001Sglebiussub run { 150290001Sglebius while (my ($macro, @args) = Mdoc::parse_line(\*STDIN, \&print_line, 151290001Sglebius \&preprocess_args) 152290001Sglebius ) { 153290001Sglebius my @ret = Mdoc::call_macro($macro, @args); 154290001Sglebius if (@ret) { 155290001Sglebius my $s = Mdoc::to_string(@ret); 156290001Sglebius print_line($s); 157290001Sglebius } 158290001Sglebius } 159290001Sglebius return 0; 160290001Sglebius} 161290001Sglebius 162290001Sglebiusexit run(@ARGV) unless caller; 163