xref: /freebsd/contrib/ntp/sntp/ag-tpl/mdoc2man (revision b5ff185e19f6013ca565b2a15bc2d6abce933f46)
1*276da39aSCy Schubert#! /usr/local/bin/perl
2*276da39aSCy Schubert
3*276da39aSCy Schubert## mdoc2man.pl -- Convert mdoc tags to man tags
4*276da39aSCy Schubert##
5*276da39aSCy Schubert## Author:	Harlan Stenn <stenn@ntp.org>
6*276da39aSCy Schubert##
7*276da39aSCy Schubert##
8*276da39aSCy Schubert##  This file is part of AutoOpts, a companion to AutoGen.
9*276da39aSCy Schubert##  AutoOpts is free software.
10*276da39aSCy Schubert##  AutoOpts is Copyright (C) 1992-2015 by Bruce Korb - all rights reserved
11*276da39aSCy Schubert##
12*276da39aSCy Schubert##  AutoOpts is available under any one of two licenses.  The license
13*276da39aSCy Schubert##  in use must be one of these two and the choice is under the control
14*276da39aSCy Schubert##  of the user of the license.
15*276da39aSCy Schubert##
16*276da39aSCy Schubert##   The GNU Lesser General Public License, version 3 or later
17*276da39aSCy Schubert##      See the files "COPYING.lgplv3" and "COPYING.gplv3"
18*276da39aSCy Schubert##
19*276da39aSCy Schubert##   The Modified Berkeley Software Distribution License
20*276da39aSCy Schubert##      See the file "COPYING.mbsd"
21*276da39aSCy Schubert##
22*276da39aSCy Schubert##  These files have the following sha256 sums:
23*276da39aSCy Schubert##
24*276da39aSCy Schubert##  8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95  COPYING.gplv3
25*276da39aSCy Schubert##  4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b  COPYING.lgplv3
26*276da39aSCy Schubert##  13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239  COPYING.mbsd
27*276da39aSCy Schubert
28*276da39aSCy Schubert### ToDo
29*276da39aSCy Schubert# Properly implement -columns in the "my %lists" definition...
30*276da39aSCy Schubert#
31*276da39aSCy Schubert# .Xr requires at least 1 arg, the code here expects at least 2
32*276da39aSCy Schubert#
33*276da39aSCy Schubert###
34*276da39aSCy Schubert
35*276da39aSCy Schubertpackage mdoc2man;
36*276da39aSCy Schubertuse strict;
37*276da39aSCy Schubertuse warnings;
38*276da39aSCy Schubertuse File::Basename;
39*276da39aSCy Schubertuse lib dirname(__FILE__);
40*276da39aSCy Schubertuse Mdoc qw(hs ns pp mapwords son soff stoggle gen_encloser);
41*276da39aSCy Schubert
42*276da39aSCy Schubert########
43*276da39aSCy Schubert## Basic
44*276da39aSCy Schubert########
45*276da39aSCy Schubert
46*276da39aSCy SchubertMdoc::def_macro( '.Sh', sub { '.SH', hs, @_ }, raw => 1);
47*276da39aSCy SchubertMdoc::def_macro( '.Ss', sub { '.SS', hs, @_ }, raw => 1);
48*276da39aSCy SchubertMdoc::def_macro( '.Pp', sub { ".sp \\n(Ppu\n.ne 2\n" } );
49*276da39aSCy SchubertMdoc::def_macro( '.Nd', sub { "\\- @_" } );
50*276da39aSCy Schubert
51*276da39aSCy Schubert# Macros that enclose things
52*276da39aSCy SchubertMdoc::def_macro( '.Brq', gen_encloser(qw({ }))          , greedy => 1 );
53*276da39aSCy SchubertMdoc::def_macro( '.Op' , gen_encloser(qw([ ]))          , greedy => 1 );
54*276da39aSCy SchubertMdoc::def_macro( '.Qq' , gen_encloser(qw(" "))          , greedy => 1 );
55*276da39aSCy SchubertMdoc::def_macro( '.Dq' , gen_encloser(qw(\*[Lq] \*[Rq])), greedy => 1 );
56*276da39aSCy SchubertMdoc::def_macro( '.Ql' , gen_encloser(qw(\[oq] \[cq]))  , greedy => 1 );
57*276da39aSCy SchubertMdoc::def_macro( '.Sq' , gen_encloser(qw(\[oq] \[cq]))  , greedy => 1 );
58*276da39aSCy SchubertMdoc::def_macro( '.Pq' , gen_encloser(qw/( )/)          , greedy => 1 );
59*276da39aSCy SchubertMdoc::def_macro( '.D1' , sub { ".in +4\n", ns, @_ , ns , "\n.in -4" } , greedy => 1);
60*276da39aSCy Schubert
61*276da39aSCy SchubertMdoc::def_macro( 'Oo',  sub { '[', @_ } );
62*276da39aSCy SchubertMdoc::def_macro( 'Oc',  sub { ']', @_ } );
63*276da39aSCy Schubert
64*276da39aSCy SchubertMdoc::def_macro( 'Po',  sub { '(', @_} );
65*276da39aSCy SchubertMdoc::def_macro( 'Pc',  sub { ')', @_ } );
66*276da39aSCy Schubert
67*276da39aSCy SchubertMdoc::def_macro( 'Bro', sub { '{', ns, @_ } );
68*276da39aSCy SchubertMdoc::def_macro( 'Brc', sub { '}', @_ } );
69*276da39aSCy Schubert
70*276da39aSCy SchubertMdoc::def_macro( '.Oo',  gen_encloser(qw([ ])), concat_until => '.Oc' );
71*276da39aSCy SchubertMdoc::def_macro( '.Bro', gen_encloser(qw({ })), concat_until => '.Brc' );
72*276da39aSCy SchubertMdoc::def_macro( '.Po',  gen_encloser(qw/( )/), concat_until => '.Pc' );
73*276da39aSCy Schubert
74*276da39aSCy SchubertMdoc::def_macro( '.Ev', sub { @_ } );
75*276da39aSCy SchubertMdoc::def_macro( '.An', sub { ".NOP ", @_, "\n.br" }, raw => 1 );
76*276da39aSCy SchubertMdoc::def_macro( '.Li', sub { mapwords {"\\f[C]$_\\f[]"} @_ } );
77*276da39aSCy SchubertMdoc::def_macro( '.Cm', sub { mapwords {"\\f\\*[B-Font]$_\\f[]"} @_ } );
78*276da39aSCy SchubertMdoc::def_macro( '.Ic', sub { mapwords {"\\f\\*[B-Font]$_\\f[]"} @_ } );
79*276da39aSCy SchubertMdoc::def_macro( '.Fl', sub { mapwords {"\\f\\*[B-Font]\\-$_\\f[]"} @_ } );
80*276da39aSCy SchubertMdoc::def_macro( '.Ar', sub { mapwords {"\\f\\*[I-Font]$_\\f[]"} @_ } );
81*276da39aSCy SchubertMdoc::def_macro( '.Em', sub { mapwords {"\\fI$_\\f[]"} @_ } );
82*276da39aSCy SchubertMdoc::def_macro( '.Va', sub { mapwords {"\\fI$_\\f[]"} @_ } );
83*276da39aSCy SchubertMdoc::def_macro( '.Sx', sub { mapwords {"\\fI$_\\f[]"} @_ } );
84*276da39aSCy SchubertMdoc::def_macro( '.Xr', sub { "\\fC".(shift)."\\f[]\\fR(".(shift).")\\f[]", @_ } );
85*276da39aSCy SchubertMdoc::def_macro( '.Fn', sub { "\\f\\*[B-Font]".(shift)."\\f[]\\fR()\\f[]" } );
86*276da39aSCy SchubertMdoc::def_macro( '.Fn', sub { "\\fB".(shift)."\\f[]\\fR()\\f[]" } );
87*276da39aSCy SchubertMdoc::def_macro( '.Fx', sub { "FreeBSD", @_ } );
88*276da39aSCy SchubertMdoc::def_macro( '.Ux', sub { "UNIX", @_ } );
89*276da39aSCy Schubert
90*276da39aSCy SchubertMdoc::def_macro( '.No', sub { ".NOP", map { ($_, ns) } @_ } );
91*276da39aSCy SchubertMdoc::def_macro( '.Pa', sub { mapwords {"\\fI$_\\f[]"} @_; } );
92*276da39aSCy Schubert{
93*276da39aSCy Schubert    my $name;
94*276da39aSCy Schubert    Mdoc::def_macro('.Nm', sub {
95*276da39aSCy Schubert        $name = shift if (!$name);
96*276da39aSCy Schubert        "\\f\\*[B-Font]$name\\fP", @_
97*276da39aSCy Schubert    } );
98*276da39aSCy Schubert}
99*276da39aSCy Schubert
100*276da39aSCy Schubert########
101*276da39aSCy Schubert## lists
102*276da39aSCy Schubert########
103*276da39aSCy Schubert
104*276da39aSCy Schubertmy %lists = (
105*276da39aSCy Schubert    bullet => sub {
106*276da39aSCy Schubert        Mdoc::def_macro('.It', sub { '.IP \fB\(bu\fP 2' });
107*276da39aSCy Schubert    },
108*276da39aSCy Schubert
109*276da39aSCy Schubert    column => sub {
110*276da39aSCy Schubert        Mdoc::def_macro('.It', sub { '.IP \fB\(bu\fP 2' });
111*276da39aSCy Schubert    },
112*276da39aSCy Schubert
113*276da39aSCy Schubert    tag    => sub {
114*276da39aSCy Schubert        my (%opts) = @_;
115*276da39aSCy Schubert
116*276da39aSCy Schubert        my $width = '';
117*276da39aSCy Schubert
118*276da39aSCy Schubert        if (exists $opts{width}) {
119*276da39aSCy Schubert            $width = ' '.((length $opts{width})+1);
120*276da39aSCy Schubert        }
121*276da39aSCy Schubert
122*276da39aSCy Schubert        if (exists $opts{compact}) {
123*276da39aSCy Schubert            my $dobrns = 0;
124*276da39aSCy Schubert            Mdoc::def_macro('.It', sub {
125*276da39aSCy Schubert                    my @ret = (".TP$width\n.NOP", hs);
126*276da39aSCy Schubert                    if ($dobrns) {
127*276da39aSCy Schubert                        ".br\n.ns\n", ns, @ret, @_;
128*276da39aSCy Schubert                    }
129*276da39aSCy Schubert                    else {
130*276da39aSCy Schubert                        $dobrns = 1;
131*276da39aSCy Schubert                        @ret, @_;
132*276da39aSCy Schubert                    }
133*276da39aSCy Schubert                }, raw => 1);
134*276da39aSCy Schubert        }
135*276da39aSCy Schubert        else {
136*276da39aSCy Schubert            Mdoc::def_macro('.It', sub {
137*276da39aSCy Schubert                    ".TP$width\n.NOP", hs, @_
138*276da39aSCy Schubert                }, raw => 1);
139*276da39aSCy Schubert        }
140*276da39aSCy Schubert    },
141*276da39aSCy Schubert);
142*276da39aSCy Schubert
143*276da39aSCy SchubertMdoc::set_Bl_callback(do { my $nested = 0; sub {
144*276da39aSCy Schubert    my $type = shift;
145*276da39aSCy Schubert    my %opts = Mdoc::parse_opts(@_);
146*276da39aSCy Schubert    if (defined $type && $type =~ /-(\w+)/ && exists $lists{$1}) {
147*276da39aSCy Schubert
148*276da39aSCy Schubert        # Wrap nested lists with .RS and .RE
149*276da39aSCy Schubert        Mdoc::set_El_callback(sub {
150*276da39aSCy Schubert                return '.RE' if $nested-- > 1;
151*276da39aSCy Schubert                return '.PP';
152*276da39aSCy Schubert            });
153*276da39aSCy Schubert
154*276da39aSCy Schubert        $lists{$1}->(%opts);
155*276da39aSCy Schubert
156*276da39aSCy Schubert        if ($nested++) {
157*276da39aSCy Schubert            return ".RS";
158*276da39aSCy Schubert        }
159*276da39aSCy Schubert        else {
160*276da39aSCy Schubert            return ();
161*276da39aSCy Schubert        }
162*276da39aSCy Schubert    }
163*276da39aSCy Schubert    else {
164*276da39aSCy Schubert        die "Invalid list type <$type>";
165*276da39aSCy Schubert    }
166*276da39aSCy Schubert}}, raw => 1);
167*276da39aSCy Schubert
168*276da39aSCy Schubert# don't bother with arguments for now and do what mdoc2man'.sh' did
169*276da39aSCy Schubert
170*276da39aSCy SchubertMdoc::def_macro('.Bd', sub { ".br\n.in +4\n.nf" } );
171*276da39aSCy SchubertMdoc::def_macro('.Ed', sub { ".in -4\n.fi" } );
172*276da39aSCy Schubert
173*276da39aSCy SchubertMdoc::set_Re_callback(sub {
174*276da39aSCy Schubert        my ($reference) = @_;
175*276da39aSCy Schubert        <<"REF";
176*276da39aSCy Schubert$reference->{authors},
177*276da39aSCy Schubert\\fI$reference->{title}\\fR,
178*276da39aSCy Schubert$reference->{optional}\n.PP
179*276da39aSCy SchubertREF
180*276da39aSCy Schubert});
181*276da39aSCy Schubert
182*276da39aSCy Schubert# Define all macros which have the same sub for inline and standalone macro
183*276da39aSCy Schubertfor (qw(Xr Em Ar Fl Ic Cm Qq Op Nm Pa Sq Li Va Brq Pq Fx Ux)) {
184*276da39aSCy Schubert    my $m = Mdoc::get_macro(".$_");
185*276da39aSCy Schubert    Mdoc::def_macro($_, delete $m->{run}, %$m);
186*276da39aSCy Schubert}
187*276da39aSCy Schubert
188*276da39aSCy Schubertsub print_line {
189*276da39aSCy Schubert    print shift;
190*276da39aSCy Schubert    print "\n";
191*276da39aSCy Schubert}
192*276da39aSCy Schubert
193*276da39aSCy Schubertsub run {
194*276da39aSCy Schubert    print <<'DEFS';
195*276da39aSCy Schubert.de1 NOP
196*276da39aSCy Schubert.  it 1 an-trap
197*276da39aSCy Schubert.  if \\n[.$] \,\\$*\/
198*276da39aSCy Schubert..
199*276da39aSCy Schubert.ie t \
200*276da39aSCy Schubert.ds B-Font [CB]
201*276da39aSCy Schubert.ds I-Font [CI]
202*276da39aSCy Schubert.ds R-Font [CR]
203*276da39aSCy Schubert.el \
204*276da39aSCy Schubert.ds B-Font B
205*276da39aSCy Schubert.ds I-Font I
206*276da39aSCy Schubert.ds R-Font R
207*276da39aSCy SchubertDEFS
208*276da39aSCy Schubert
209*276da39aSCy Schubert    while (my ($macro, @args) = Mdoc::parse_line(\*STDIN, \&print_line)) {
210*276da39aSCy Schubert        my @ret = Mdoc::call_macro($macro, @args);
211*276da39aSCy Schubert        print_line(Mdoc::to_string(@ret)) if @ret;
212*276da39aSCy Schubert    }
213*276da39aSCy Schubert    return 0;
214*276da39aSCy Schubert}
215*276da39aSCy Schubert
216*276da39aSCy Schubertexit run(@ARGV) unless caller;
217*276da39aSCy Schubert
218*276da39aSCy Schubert1;
219*276da39aSCy Schubert__END__
220