| 1 |
#!/usr/bin/perl -w
|
| 2 |
|
| 3 |
# Script parses the XML file for the appendix on preseeding and extracts
|
| 4 |
# example snippts to form the raw preseed example file. Section titles are
|
| 5 |
# added as headers.
|
| 6 |
# The script will include all text between <informalexample> tags that have
|
| 7 |
# the attribute 'role="example"' set, except if a 'condition' attribute is
|
| 8 |
# in force that does not match the specified release or if an 'arch' attribute
|
| 9 |
# is in force that does not match the specified architecture.
|
| 10 |
|
| 11 |
# Define module to use
|
| 12 |
use HTML::Parser();
|
| 13 |
use Getopt::Std;
|
| 14 |
|
| 15 |
local %tagstatus;
|
| 16 |
local %example;
|
| 17 |
local %ignore;
|
| 18 |
local $prevtag = '';
|
| 19 |
local $titletag;
|
| 20 |
local $settitle = 0;
|
| 21 |
|
| 22 |
$example{'print'} = 0;
|
| 23 |
$example{'in_sect'} = 0;
|
| 24 |
$example{'first'} = 1;
|
| 25 |
$example{'new'} = 0;
|
| 26 |
|
| 27 |
getopts('hda:r:') || die "Unknown command line arguments! Try $0 -h\n";
|
| 28 |
use vars qw($opt_h $opt_d $opt_a $opt_r);
|
| 29 |
|
| 30 |
if ($opt_h) {
|
| 31 |
print <<END;
|
| 32 |
preseed.pl: parses preseed appendix xml file to extract preseed example file
|
| 33 |
|
| 34 |
Usage: $0 [-hdac] <xml-file>
|
| 35 |
|
| 36 |
Options:
|
| 37 |
-h display this help information
|
| 38 |
-d debug mode
|
| 39 |
-a <arch> architecture for which to generate the example
|
| 40 |
(default: i386)
|
| 41 |
-r <release> release for which to generate the example (required)
|
| 42 |
END
|
| 43 |
exit 0;
|
| 44 |
}
|
| 45 |
|
| 46 |
die "Must specify release for which to generate example." if ! $opt_r;
|
| 47 |
|
| 48 |
my $xmlfile = shift;
|
| 49 |
die "Must specify XML file to parse!" if ! $xmlfile;
|
| 50 |
die "Specified XML file \"$xmlfile\" not found." if ! -f $xmlfile;
|
| 51 |
|
| 52 |
my $arch = $opt_a ? "$opt_a" : "i386";
|
| 53 |
my $release = $opt_r;
|
| 54 |
|
| 55 |
|
| 56 |
# Create instance
|
| 57 |
$p = HTML::Parser->new(
|
| 58 |
start_h => [\&start_rtn, 'tagname, text, attr'],
|
| 59 |
text_h => [\&text_rtn, 'text'],
|
| 60 |
end_h => [\&end_rtn, 'tagname']);
|
| 61 |
|
| 62 |
# Start parsing the specified file
|
| 63 |
$p->parse_file($xmlfile);
|
| 64 |
|
| 65 |
# Execute when start tag is encountered
|
| 66 |
sub start_rtn {
|
| 67 |
my ($tagname, $text, $attr) = @_;
|
| 68 |
print STDERR "\nStart: $tagname\n" if $opt_d;
|
| 69 |
if ( $tagname =~ /appendix|sect1|sect2|sect3|para/ ) {
|
| 70 |
$tagstatus{$tagname}{'count'} += 1;
|
| 71 |
print STDERR "$tagname $tagstatus{$tagname}{'count'}\n" if $opt_d;
|
| 72 |
|
| 73 |
if ( ! exists $ignore{'tag'} ) {
|
| 74 |
if ( exists $attr->{condition} ) {
|
| 75 |
print STDERR "Condition: $attr->{condition}\n" if $opt_d;
|
| 76 |
if ( $attr->{condition} ne $release ) {
|
| 77 |
$ignore{'tag'} = $tagname;
|
| 78 |
$ignore{'depth'} = $tagstatus{$tagname}{'count'};
|
| 79 |
print STDERR "Start ignore because of condition" if $opt_d;
|
| 80 |
}
|
| 81 |
}
|
| 82 |
if ( exists $attr->{arch} ) {
|
| 83 |
print STDERR "Architecture: $attr->{arch}\n" if $opt_d;
|
| 84 |
if ( $attr->{arch} ne $arch ) {
|
| 85 |
$ignore{'tag'} = $tagname;
|
| 86 |
$ignore{'depth'} = $tagstatus{$tagname}{'count'};
|
| 87 |
print STDERR "Start ignore because of architecture" if $opt_d;
|
| 88 |
}
|
| 89 |
}
|
| 90 |
}
|
| 91 |
}
|
| 92 |
# Assumes that <title> is the first tag after a section tag
|
| 93 |
if ( $prevtag =~ /sect1|sect2|sect3/ ) {
|
| 94 |
$settitle = ( $tagname eq 'title' );
|
| 95 |
$titletag = $prevtag;
|
| 96 |
$example{'in_sect'} = 0;
|
| 97 |
}
|
| 98 |
$prevtag = $tagname;
|
| 99 |
if ( $tagname eq 'informalexample' && ! exists $ignore{'tag'} ) {
|
| 100 |
if ( exists $attr->{role} && $attr->{role} eq "example" ) {
|
| 101 |
$example{'print'} = 1;
|
| 102 |
$example{'new'} = 1;
|
| 103 |
}
|
| 104 |
}
|
| 105 |
}
|
| 106 |
|
| 107 |
# Execute when text is encountered
|
| 108 |
sub text_rtn {
|
| 109 |
my ($text) = @_;
|
| 110 |
if ( $settitle ) {
|
| 111 |
# Clean leading and trailing whitespace for titles
|
| 112 |
$text =~ s/^[[:space:]]*//;
|
| 113 |
$text =~ s/[[:space:]]*$//;
|
| 114 |
$tagstatus{$titletag}{'title'} = $text;
|
| 115 |
$settitle = 0;
|
| 116 |
}
|
| 117 |
if ( $example{'print'} ) {
|
| 118 |
# Print section headers
|
| 119 |
for ($s=1; $s<=3; $s++) {
|
| 120 |
my $sect="sect$s";
|
| 121 |
if ( $tagstatus{$sect}{'title'} ) {
|
| 122 |
print "\n" if ( $s == 1 && ! $example{'first'} );
|
| 123 |
for ( $i = 1; $i <= 5 - $s; $i++ ) { print "#"; };
|
| 124 |
print " $tagstatus{$sect}{'title'}\n";
|
| 125 |
delete $tagstatus{$sect}{'title'};
|
| 126 |
}
|
| 127 |
}
|
| 128 |
|
| 129 |
# Clean leading whitespace
|
| 130 |
if ( $example{'new'} ) {
|
| 131 |
$text =~ s/^[[:space:]]*//;
|
| 132 |
}
|
| 133 |
|
| 134 |
print "$text";
|
| 135 |
|
| 136 |
$example{'first'} = 0;
|
| 137 |
$example{'new'} = 0;
|
| 138 |
$example{'in_sect'} = 1;
|
| 139 |
}
|
| 140 |
}
|
| 141 |
|
| 142 |
# Execute when the end tag is encountered
|
| 143 |
sub end_rtn {
|
| 144 |
my ($tagname) = @_;
|
| 145 |
print STDERR "\nEnd: $tagname\n" if $opt_d;
|
| 146 |
if ( $tagname eq 'informalexample' ) {
|
| 147 |
$example{'print'} = 0;
|
| 148 |
}
|
| 149 |
if ( $tagname =~ /appendix|sect1|sect2|sect3|para/ ) {
|
| 150 |
delete $tagstatus{$tagname}{'title'} if exists $tagstatus{$tagname}{'title'};
|
| 151 |
|
| 152 |
if ( exists $ignore{'tag'} ) {
|
| 153 |
if ( $ignore{'tag'} eq $tagname && $ignore{'depth'} == $tagstatus{$tagname}{'count'} ) {
|
| 154 |
delete $ignore{'tag'};
|
| 155 |
}
|
| 156 |
}
|
| 157 |
|
| 158 |
if ( $example{'in_sect'} ) {
|
| 159 |
print "\n";
|
| 160 |
$example{'in_sect'} = 0;
|
| 161 |
}
|
| 162 |
$tagstatus{$tagname}{'count'} -= 1;
|
| 163 |
print STDERR "$tagname $tagstatus{$tagname}{'count'}\n" if $opt_d;
|
| 164 |
die "Invalid XML file: negative count for tag <$tagname>!" if $tagstatus{$tagname}{'count'} < 0;
|
| 165 |
}
|
| 166 |
}
|