1275970Scy#! /usr/bin/perl 2275970Scy 3275970Scy### To Do: 4275970Scy 5275970Scy# the Bl -column command needs work: 6275970Scy# - support for "-offset" 7275970Scy# - support for the header widths 8275970Scy 9275970Scy# 10275970Scy 11275970Scy### 12275970Scy 13275970Scypackage mdoc2texi; 14275970Scyuse strict; 15275970Scyuse warnings; 16275970Scyuse File::Basename qw(dirname); 17275970Scyuse lib dirname(__FILE__); 18275970Scyuse Mdoc qw(ns pp hs mapwords gen_encloser nl); 19275970Scy 20275970Scy# Ignore commments 21275970ScyMdoc::def_macro( '.\"', sub { () } ); 22275970Scy 23275970Scy# Enclosers 24275970ScyMdoc::def_macro( '.An', sub { @_, ns, '@*' } ); 25275970ScyMdoc::def_macro( '.Aq', gen_encloser(qw(< >)), greedy => 1); 26275970ScyMdoc::def_macro( '.Bq', gen_encloser(qw([ ])), greedy => 1); 27275970ScyMdoc::def_macro( '.Brq', gen_encloser(qw(@{ @})), greedy => 1); 28275970ScyMdoc::def_macro( '.Pq', gen_encloser(qw/( )/), greedy => 1); 29275970ScyMdoc::def_macro( '.Qq', gen_encloser(qw(" ")), greedy => 1); 30275970ScyMdoc::def_macro( '.Op', gen_encloser(qw(@code{[ ]})), greedy => 1); 31275970ScyMdoc::def_macro( '.Ql', gen_encloser(qw(@quoteleft{} @quoteright{})), 32275970Scy greedy => 1); 33275970ScyMdoc::def_macro( '.Sq', gen_encloser(qw(@quoteleft{} @quoteright{})), 34275970Scy greedy => 1); 35275970ScyMdoc::def_macro( '.Dq', gen_encloser(qw(@quotedblleft{} @quotedblright{})), 36275970Scy greedy => 1); 37275970ScyMdoc::def_macro( '.Eq', sub { 38275970Scy my ($o, $c) = (shift, pop); 39275970Scy gen_encloser($o, $c)->(@_) 40275970Scy}, greedy => 1); 41275970ScyMdoc::def_macro( '.D1', sub { "\@example\n", ns, @_, ns, "\n\@end example" }, 42275970Scy greedy => 1); 43275970ScyMdoc::def_macro( '.Dl', sub { "\@example\n", ns, @_, ns, "\n\@end example" }, 44275970Scy greedy => 1); 45275970Scy 46275970ScyMdoc::def_macro( '.Oo', gen_encloser(qw(@code{[ ]})), concat_until => '.Oc'); 47275970ScyMdoc::def_macro( 'Oo', sub { '@code{[', ns, @_ } ); 48275970ScyMdoc::def_macro( 'Oc', sub { @_, ns, pp(']}') } ); 49275970Scy 50275970ScyMdoc::def_macro( '.Bro', gen_encloser(qw(@code{@{ @}})), concat_until => '.Brc'); 51275970ScyMdoc::def_macro( 'Bro', sub { '@code{@{', ns, @_ } ); 52275970ScyMdoc::def_macro( 'Brc', sub { @_, ns, pp('@}}') } ); 53275970Scy 54275970ScyMdoc::def_macro( '.Po', gen_encloser(qw/( )/), concat_until => '.Pc'); 55275970ScyMdoc::def_macro( 'Po', sub { '(', @_ } ); 56275970ScyMdoc::def_macro( 'Pc', sub { @_, ')' } ); 57275970Scy 58275970ScyMdoc::def_macro( '.Ar', sub { mapwords {"\@kbd{$_}"} @_ } ); 59275970ScyMdoc::def_macro( '.Fl', sub { mapwords {"\@code{-$_}"} @_ } ); 60275970ScyMdoc::def_macro( '.Cm', sub { mapwords {"\@code{-$_}"} @_ } ); 61275970ScyMdoc::def_macro( '.Ic', sub { mapwords {"\@code{$_}"} @_ } ); 62275970ScyMdoc::def_macro( '.Cm', sub { mapwords {"\@code{$_}"} @_ } ); 63275970ScyMdoc::def_macro( '.Li', sub { mapwords {"\@code{$_}"} @_ } ); 64275970ScyMdoc::def_macro( '.Va', sub { mapwords {"\@code{$_}"} @_ } ); 65275970ScyMdoc::def_macro( '.Em', sub { mapwords {"\@emph{$_}"} @_ } ); 66275970ScyMdoc::def_macro( '.Fn', sub { '@code{'.(shift).'()}' } ); 67275970ScyMdoc::def_macro( '.Ss', sub { "\@subsubsection", hs, @_ }); 68275970ScyMdoc::def_macro( '.Sh', sub { 69275970Scy my $name = "@_"; 70275970Scy "\@node", hs, "$name\n", ns, "\@subsection", hs, $name 71275970Scy }); 72275970ScyMdoc::def_macro( '.Ss', sub { "\@subsubsection", hs, @_ }); 73275970ScyMdoc::def_macro( '.Xr', sub { '@code{'.(shift).'('.(shift).')}', @_ } ); 74275970ScyMdoc::def_macro( '.Sx', gen_encloser(qw(@ref{ })) ); 75275970ScyMdoc::def_macro( '.Ux', sub { '@sc{unix}', @_ } ); 76275970ScyMdoc::def_macro( '.Fx', sub { '@sc{freebsd}', @_ } ); 77275970Scy{ 78275970Scy my $name; 79275970Scy Mdoc::def_macro('.Nm', sub { 80275970Scy $name = shift || $ENV{AG_DEF_PROG_NAME} || 'XXX' if (!$name); 81275970Scy "\@code{$name}" 82275970Scy } ); 83275970Scy} 84275970ScyMdoc::def_macro( '.Pa', sub { mapwords {"\@file{$_}"} @_ } ); 85275970ScyMdoc::def_macro( '.Pp', sub { '' } ); 86275970Scy 87275970Scy# Setup references 88275970Scy 89275970ScyMdoc::def_macro( '.Rs', sub { "\@*\n", @_ } ); 90275970ScyMdoc::set_Re_callback(sub { 91275970Scy my ($reference) = @_; 92275970Scy "@*\n", ns, $reference->{authors}, ',', "\@emph{$reference->{title}}", 93275970Scy ',', $reference->{optional} 94275970Scy }); 95275970Scy 96275970Scy# Set up Bd/Ed 97275970Scy 98275970Scymy %displays = ( 99275970Scy literal => [ '@verbatim', '@end verbatim' ], 100275970Scy); 101275970Scy 102275970ScyMdoc::def_macro( '.Bd', sub { 103275970Scy (my $type = shift) =~ s/^-//; 104275970Scy die "Not supported display type <$type>" 105275970Scy if not exists $displays{ $type }; 106275970Scy 107275970Scy my $orig_ed = Mdoc::get_macro('.Ed'); 108275970Scy Mdoc::def_macro('.Ed', sub { 109275970Scy Mdoc::def_macro('.Ed', delete $orig_ed->{run}, %$orig_ed); 110275970Scy $displays{ $type }[1]; 111275970Scy }); 112275970Scy $displays{ $type }[0] 113275970Scy }); 114275970ScyMdoc::def_macro('.Ed', sub { die '.Ed used but .Bd was not seen' }); 115275970Scy 116275970Scy# Set up Bl/El 117275970Scy 118275970Scymy %lists = ( 119275970Scy bullet => [ '@itemize @bullet', '@end itemize' ], 120275970Scy tag => [ '@table @asis', '@end table' ], 121275970Scy column => [ '@table @asis', '@end table' ], 122275970Scy); 123275970Scy 124275970ScyMdoc::set_Bl_callback(sub { 125275970Scy my $type = shift; 126275970Scy die "Specify a list type" if not defined $type; 127275970Scy $type =~ s/^-//; 128275970Scy die "Not supported list type <$type>" if not exists $lists{ $type }; 129275970Scy Mdoc::set_El_callback(sub { $lists{ $type }[1] }); 130275970Scy $lists{ $type }[0] 131275970Scy }); 132275970ScyMdoc::def_macro('.It', sub { '@item', hs, @_ }); 133275970Scy 134275970Scyfor (qw(Aq Bq Brq Pq Qq Ql Sq Dq Eq Ar Fl Ic Pa Op Cm Li Fx Ux Va)) { 135275970Scy my $m = Mdoc::get_macro(".$_"); 136275970Scy Mdoc::def_macro($_, delete $m->{run}, %$m); 137275970Scy} 138275970Scy 139275970Scysub print_line { 140275970Scy my $s = shift; 141275970Scy $s =~ s/\\&//g; 142275970Scy print "$s\n"; 143275970Scy} 144275970Scy 145275970Scysub preprocess_args { 146275970Scy $_ =~ s/([{}])/\@$1/g for @_; 147275970Scy} 148275970Scy 149275970Scysub run { 150275970Scy while (my ($macro, @args) = Mdoc::parse_line(\*STDIN, \&print_line, 151275970Scy \&preprocess_args) 152275970Scy ) { 153275970Scy my @ret = Mdoc::call_macro($macro, @args); 154275970Scy if (@ret) { 155275970Scy my $s = Mdoc::to_string(@ret); 156275970Scy print_line($s); 157275970Scy } 158275970Scy } 159275970Scy return 0; 160275970Scy} 161275970Scy 162275970Scyexit run(@ARGV) unless caller; 163