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