#!/usr/bin/perl -w # xmltoman - simple xml to man converter # Copyright (C) 2000-2002 Oliver Kurth # 2003 Lennart Poettering # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA use XML::Parser; my $buffer = ""; my $break_req = 0; my @stack; my $stack_n = 0; my $para = 0; sub out { my $t = shift; if ($t ne "") { print $t; $break_req=1; } } sub out_buf { local $_; my $space = shift; $_ = $buffer; $buffer = ""; s/\n/\ /gm; s/\s+/\ /gm; s/^\s*//gm if (!$break_req); s/^\s$//gm if (!$space); out($_); } sub stack_push { my $a = shift; if ($stack_n == 0 or $a ne $stack[$stack_n-1]) { out("\\fB") if $a =~ /^bold$/; out("\\fI") if $a =~ /^italic$/; } $stack[$stack_n++] = $a; } sub stack_pop { local $_; if ($stack_n > 0) { $stack_n--; if ($stack_n > 0) { $a = $stack[$stack_n-1]; out("\\fB") if $a =~ /^bold$/; out("\\fI") if $a =~ /^italic$/; } else { out("\\f1"); } } } sub handle_start { local $_; my $expat = shift; my $element = shift; my %attr = @_; $_ = $element; if (/^manpage$/) { out_buf(0); print "\n" if ($break_req); print ".TH " . $attr{name} . " " . $attr{section} . " User Manuals\n"; print ".SH NAME\n"; print $attr{name} . " \\- " . $attr{desc} . "\n"; $break_req = 0; } elsif (/^synopsis$/) { out_buf(0); print "\n" if ($break_req); print ".SH SYNOPSIS\n"; $section = $element; $break_req = 0; stack_push("bold"); } elsif (/^description$/) { out_buf(0); print "\n" if ($break_req); print ".SH DESCRIPTION\n"; $section = $element; $break_req = 0; } elsif (/^options$/) { out_buf(0); print "\n" if ($break_req); print ".SH OPTIONS\n"; $section = $element; $break_req = 0; } elsif (/^seealso$/) { out_buf(0); print "\n" if ($break_req); print ".SH SEE ALSO\n"; $section = $element; $break_req = 0; } elsif (/^section$/) { out_buf(0); print "\n" if ($break_req); print ".SH ".uc($attr{name})."\n"; $section = $attr{name}; $break_req = 0; } elsif (/^option$/) { out_buf(0); print "\n" if ($break_req); print ".TP\n"; $break_req = 0; } elsif (/^p$/ or /^cmd$/) { out_buf(0); print "\n" if ($para); $break_req = 0; } elsif (/^optdesc$/) { out_buf(0); $break_req = 0; } elsif (/^arg$/ or /^file$/) { out_buf(1); stack_push("italic"); } elsif (/^opt$/) { out_buf(1); stack_push("bold"); } elsif (/^manref$/) { out_buf(1); stack_push("bold"); out($attr{name} ."(" . $attr{section} . ")"); stack_pop(); } elsif (/^url$/) { out_buf(1); stack_push("bold"); out($attr{href}); stack_pop(); }; $para = 0; } sub handle_end { local $_; my $expat = shift; my $element = shift; $_ = $element; $para = 0; if (/^description$/ or /^options$/ or /^section$/ or /^seealso$/) { out_buf(0); } elsif (/^p$/ or /^cmd$/) { out_buf(0); print "\n" if ($break_req); $para = 1; $break_req = 0; } elsif (/^synopsis$/) { out_buf(0); stack_pop(); } elsif (/^opt$/ or /^arg$/ or /^file$/) { out_buf(1); stack_pop(); } elsif (/^manpage$/) { out_buf(0); print "\n" if $break_req; $break_req = 0; } elsif (/^optdesc$/ or /^cmd$/ or /^option$/) { # Simply ignore } else { out_buf(1); } }; sub handle_char { local $_; my $expat = shift; my $string = shift; $buffer .= $string; } MAIN:{ my $file = shift; if (!$file) { print STDERR "You need to specify a file to parse\n"; exit(1); } my $parser = new XML::Parser(Handlers => { Start => \&handle_start, End => \&handle_end, Char => \&handle_char}); $parser->parsefile($file, ProtocolEncoding => 'ISO-8859-1'); }