• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/perl -w
2
3#    xmltoman - simple xml to man converter
4#    Copyright (C) 2000-2002 Oliver Kurth <oku@masqmail.cx>
5#                       2003 Lennart Poettering <mzkzygbzna@0pointer.de>
6#
7#    This program is free software; you can redistribute it and/or modify
8#    it under the terms of the GNU General Public License as published by
9#    the Free Software Foundation; either version 2 of the License, or
10#    (at your option) any later version.
11#
12#    This program is distributed in the hope that it will be useful,
13#    but WITHOUT ANY WARRANTY; without even the implied warranty of
14#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15#    GNU General Public License for more details.
16#
17#    You should have received a copy of the GNU General Public License
18#    along with this program; if not, see <http://www.gnu.org/licenses/>.
19
20use XML::Parser;
21
22my $buffer = "";
23my $break_req = 0;
24
25my @stack;
26my $stack_n = 0;
27
28my $para = 0;
29
30sub out {
31    my $t = shift;
32
33    if ($t ne "") {
34        print $t;
35        $break_req=1;
36    }
37}
38
39sub out_buf {
40    local $_;
41
42    my $space = shift;
43
44    $_ = $buffer;
45    $buffer = "";
46
47    s/\n/\ /gm;
48    s/\s+/\ /gm;
49    s/^\s*//gm if (!$break_req);
50    s/^\s$//gm if (!$space);
51
52    out($_);
53}
54
55sub stack_push {
56    my $a = shift;
57
58    if ($stack_n == 0 or $a ne $stack[$stack_n-1]) {
59        out("\\fB") if $a =~ /^bold$/;
60        out("\\fI") if $a =~ /^italic$/;
61    }
62
63    $stack[$stack_n++] = $a;
64}
65
66sub stack_pop {
67    local $_;
68
69    if ($stack_n > 0) {
70        $stack_n--;
71
72        if ($stack_n > 0) {
73            $a = $stack[$stack_n-1];
74            out("\\fB") if $a =~ /^bold$/;
75            out("\\fI") if $a =~ /^italic$/;
76        } else {
77            out("\\f1");
78        }
79    }
80}
81
82sub handle_start {
83    local $_;
84    my $expat = shift;
85    my $element = shift;
86    my %attr = @_;
87
88    $_ = $element;
89
90    if (/^manpage$/) {
91        out_buf(0);
92        print "\n" if ($break_req);
93        print ".TH " . $attr{name} . " " . $attr{section} . " User Manuals\n";
94        print ".SH NAME\n";
95        print $attr{name} . " \\- " . $attr{desc} . "\n";
96        $break_req = 0;
97    } elsif (/^synopsis$/) {
98        out_buf(0);
99        print "\n" if ($break_req);
100        print ".SH SYNOPSIS\n";
101        $section = $element;
102        $break_req = 0;
103        stack_push("bold");
104    } elsif (/^description$/) {
105        out_buf(0);
106        print "\n" if ($break_req);
107        print ".SH DESCRIPTION\n";
108        $section = $element;
109        $break_req = 0;
110    } elsif (/^options$/) {
111        out_buf(0);
112        print "\n" if ($break_req);
113        print ".SH OPTIONS\n";
114        $section = $element;
115        $break_req = 0;
116    } elsif (/^seealso$/) {
117        out_buf(0);
118        print "\n" if ($break_req);
119        print ".SH SEE ALSO\n";
120        $section = $element;
121        $break_req = 0;
122    } elsif (/^section$/) {
123        out_buf(0);
124        print "\n" if ($break_req);
125        print ".SH ".uc($attr{name})."\n";
126        $section = $attr{name};
127        $break_req = 0;
128    } elsif (/^option$/) {
129        out_buf(0);
130        print "\n" if ($break_req);
131        print ".TP\n";
132        $break_req = 0;
133    } elsif (/^p$/ or /^cmd$/) {
134        out_buf(0);
135        print "\n" if ($para);
136        $break_req = 0;
137    } elsif (/^optdesc$/) {
138        out_buf(0);
139        $break_req = 0;
140    } elsif (/^arg$/ or /^file$/) {
141        out_buf(1);
142        stack_push("italic");
143    } elsif (/^opt$/) {
144        out_buf(1);
145        stack_push("bold");
146    } elsif (/^manref$/) {
147        out_buf(1);
148        stack_push("bold");
149        out($attr{name} ."(" . $attr{section} . ")");
150        stack_pop();
151    } elsif (/^url$/) {
152        out_buf(1);
153        stack_push("bold");
154        out($attr{href});
155        stack_pop();
156    };
157
158    $para = 0;
159}
160
161sub handle_end {
162    local $_;
163    my $expat = shift;
164    my $element = shift;
165
166    $_ = $element;
167
168    $para = 0;
169
170    if (/^description$/ or /^options$/ or /^section$/ or /^seealso$/) {
171        out_buf(0);
172    } elsif (/^p$/ or /^cmd$/) {
173        out_buf(0);
174        print "\n" if ($break_req);
175        $para = 1;
176        $break_req = 0;
177    } elsif (/^synopsis$/) {
178        out_buf(0);
179        stack_pop();
180    } elsif (/^opt$/ or /^arg$/ or /^file$/) {
181        out_buf(1);
182        stack_pop();
183    } elsif (/^manpage$/) {
184        out_buf(0);
185        print "\n" if $break_req;
186        $break_req = 0;
187    } elsif (/^optdesc$/ or /^cmd$/ or /^option$/) {
188        # Simply ignore
189    } else {
190        out_buf(1);
191    }
192};
193
194sub handle_char {
195    local $_;
196    my $expat = shift;
197    my $string = shift;
198
199    $buffer .= $string;
200}
201
202MAIN:{
203    my $file = shift;
204
205    if (!$file) {
206        print STDERR "You need to specify a file to parse\n";
207        exit(1);
208    }
209
210    my $parser = new XML::Parser(Handlers => {
211        Start => \&handle_start,
212        End => \&handle_end,
213        Char => \&handle_char});
214
215    $parser->parsefile($file, ProtocolEncoding => 'ISO-8859-1');
216}
217