192ddea16Smrg#!/usr/bin/env perl 2154daed1Smrg 3154daed1Smrg# converts the <rules>.xml file to the old format <rules>.lst file 4154daed1Smrg# 5154daed1Smrg# Usage: 6154daed1Smrg# 7bfd7cbc1Smrg# perl xml2lst.pl < filename.xml > filename.lst 8154daed1Smrg# 9154daed1Smrg# author Ivan Pascal 10154daed1Smrg 11154daed1Smrg$doc = new_document( 0, ''); 12154daed1Smrgparse('', $doc); 13154daed1Smrg 14154daed1Smrg($reg) = node_by_name($doc, '/xkbConfigRegistry'); 15154daed1Smrg@models = node_by_name($reg, 'modelList/model/configItem'); 16154daed1Smrg@layouts = node_by_name($reg, 'layoutList/layout/configItem'); 17154daed1Smrg@options = node_by_name($reg, 'optionList/group/configItem'); 18154daed1Smrg 19154daed1Smrgprint "! model\n"; 20154daed1Smrgfor $i (@models) { 21154daed1Smrg ($name) = node_by_name($i, 'name'); 22bfd7cbc1Smrg ($descr) = node_by_name($i, 'description'); 23154daed1Smrg printf(" %-15s %s\n", text_child($name), text_child($descr)); 24154daed1Smrg} 25154daed1Smrg 26154daed1Smrgprint "\n! layout\n"; 27154daed1Smrgfor $i (@layouts) { 28154daed1Smrg ($name) = node_by_name($i, 'name'); 29bfd7cbc1Smrg ($descr) = node_by_name($i, 'description'); 30154daed1Smrg printf(" %-15s %s\n", text_child($name), text_child($descr)); 31154daed1Smrg} 32154daed1Smrg 33154daed1Smrgprint "\n! variant\n"; 34154daed1Smrgfor $l (@layouts) { 35154daed1Smrg ($lname) = node_by_name($l, 'name'); 36154daed1Smrg @variants = node_by_name($l, '../variantList/variant/configItem'); 37154daed1Smrg for $v (@variants) { 38154daed1Smrg ($name) = node_by_name($v, 'name'); 39bfd7cbc1Smrg ($descr) = node_by_name($v, 'description'); 40154daed1Smrg printf(" %-15s %s: %s\n", 41154daed1Smrg text_child($name), text_child($lname), text_child($descr)); 42154daed1Smrg } 43154daed1Smrg} 44154daed1Smrg 45154daed1Smrgprint "\n! option\n"; 46154daed1Smrgfor $g (@options) { 47154daed1Smrg ($name) = node_by_name($g, 'name'); 48bfd7cbc1Smrg ($descr) = node_by_name($g, 'description'); 49154daed1Smrg printf(" %-20s %s\n", text_child($name), text_child($descr)); 50154daed1Smrg 51154daed1Smrg @opts = node_by_name($g, '../option/configItem'); 52154daed1Smrg for $o (@opts) { 53154daed1Smrg ($name) = node_by_name($o, 'name'); 54bfd7cbc1Smrg ($descr) = node_by_name($o, 'description'); 55154daed1Smrg printf(" %-20s %s\n", 56154daed1Smrg text_child($name), text_child($descr)); 57154daed1Smrg } 58154daed1Smrg} 59154daed1Smrg 60154daed1Smrgsub with_attribute { 61154daed1Smrg local ($nodelist, $attrexpr) = @_; 62154daed1Smrg local ($attr, $value) = split (/=/, $attrexpr); 63154daed1Smrg local ($node, $attrvalue); 64154daed1Smrg if (defined $value && $value ne '') { 65154daed1Smrg $value =~ s/"//g; 66154daed1Smrg foreach $node (@{$nodelist}) { 67154daed1Smrg $attrvalue = node_attribute($node, $attr); 68154daed1Smrg if (defined $attrvalue && $attrvalue eq $value) { 69154daed1Smrg return $node; 70154daed1Smrg } 71154daed1Smrg } 72154daed1Smrg } else { 73154daed1Smrg foreach $node (@{$nodelist}) { 74154daed1Smrg if (! defined node_attribute($node, $attr)) { 75154daed1Smrg return $node; 76154daed1Smrg } 77154daed1Smrg } 78154daed1Smrg } 79154daed1Smrg undef; 80154daed1Smrg} 81154daed1Smrg 82154daed1Smrg# Subroutines 83154daed1Smrg 84154daed1Smrgsub parse { 85154daed1Smrg local $intag = 0; 86154daed1Smrg my (@node_stack, $parent); 87154daed1Smrg $parent = @_[1]; 88154daed1Smrg local ($tag, $text); 89154daed1Smrg 90154daed1Smrg while (<>) { 91154daed1Smrg chomp; 92154daed1Smrg @str = split /([<>])/; 93154daed1Smrg shift @str if ($str[0] eq '' || $str[0] =~ /^[ \t]*$/); 94154daed1Smrg 95154daed1Smrg while (scalar @str) { 96154daed1Smrg $token = shift @str; 97154daed1Smrg if ($token eq '<') { 98154daed1Smrg $intag = 1; 99154daed1Smrg if (defined $text) { 100154daed1Smrg add_text_node($parent, $text); 101154daed1Smrg undef $text; 102154daed1Smrg } 103154daed1Smrg } elsif ($token eq '>') { 104154daed1Smrg $intag = 0; 105154daed1Smrg if ($tag =~ /^\/(.*)/) { # close tag 106154daed1Smrg $parent = pop @node_stack; 107154daed1Smrg } elsif ($tag =~ /^([^\/]*)\/$/) { 108154daed1Smrg empty_tag($parent, $1); 109154daed1Smrg } else { 110154daed1Smrg if (defined ($node = open_tag($parent, $tag))) { 111154daed1Smrg push @node_stack, $parent; 112154daed1Smrg $parent = $node; 113154daed1Smrg } 114154daed1Smrg } 115154daed1Smrg undef $tag; 116154daed1Smrg } else { 117154daed1Smrg if ($intag == 1) { 118154daed1Smrg if (defined $tag) { 119154daed1Smrg $tag .= ' '. $token; 120154daed1Smrg } else { 121154daed1Smrg $tag = $token; 122154daed1Smrg } 123154daed1Smrg } else { 124154daed1Smrg if (defined $text) { 125154daed1Smrg $text .= "\n" . $token; 126154daed1Smrg } else { 127154daed1Smrg $text = $token; 128154daed1Smrg } 129154daed1Smrg } 130154daed1Smrg } 131154daed1Smrg } 132154daed1Smrg } 133154daed1Smrg} 134154daed1Smrg 135154daed1Smrgsub new_document { 136154daed1Smrg $doc = new_node( 0, '', 'DOCUMENT'); 137154daed1Smrg $doc->{CHILDREN} = []; 138154daed1Smrg return $doc; 139154daed1Smrg} 140154daed1Smrg 141154daed1Smrgsub new_node { 142154daed1Smrg local ($parent_node, $tag, $type) = @_; 143154daed1Smrg 144154daed1Smrg my %node; 145154daed1Smrg $node{PARENT} = $parent_node; 146154daed1Smrg $node{TYPE} = $type; 147154daed1Smrg 148154daed1Smrg if ($type eq 'COMMENT' || $type eq 'TEXT') { 149154daed1Smrg $node{TEXT} = $tag; 150154daed1Smrg $node{NAME} = $type; 151154daed1Smrg return \%node; 152154daed1Smrg } 153154daed1Smrg 154154daed1Smrg local ($tname, $attr) = split(' ', $tag, 2); 155154daed1Smrg $node{NAME} = $tname; 156154daed1Smrg 157154daed1Smrg if (defined $attr && $attr ne '') { 158154daed1Smrg my %attr_table; 159154daed1Smrg local @attr_list = split ( /"/, $attr); 160154daed1Smrg local ($name, $value); 161154daed1Smrg while (scalar @attr_list) { 162154daed1Smrg $name = shift @attr_list; 163154daed1Smrg $name =~ s/[ =]//g; 164154daed1Smrg next if ($name eq ''); 165154daed1Smrg $value = shift @attr_list; 166154daed1Smrg $attr_table{$name} =$value; 167154daed1Smrg } 168154daed1Smrg $node{ATTRIBUTES} = \%attr_table; 169154daed1Smrg } 170154daed1Smrg return \%node; 171154daed1Smrg} 172154daed1Smrg 173154daed1Smrgsub add_node { 174154daed1Smrg local ($parent_node, $node) = @_; 175154daed1Smrg push @{$parent_node->{CHILDREN}}, $node; 176154daed1Smrg 177154daed1Smrg local $tname = $node->{NAME}; 178154daed1Smrg if (defined $parent_node->{$tname}) { 179154daed1Smrg push @{$parent_node->{$tname}}, $node 180154daed1Smrg } else { 181154daed1Smrg $parent_node->{$tname} = [ $node ]; 182154daed1Smrg } 183154daed1Smrg} 184154daed1Smrg 185154daed1Smrgsub empty_tag { 186154daed1Smrg local ($parent_node, $tag) = @_; 187154daed1Smrg local $node = new_node($parent_node, $tag, 'EMPTY'); 188154daed1Smrg add_node($parent_node, $node); 189154daed1Smrg} 190154daed1Smrg 191154daed1Smrgsub open_tag { 192154daed1Smrg local ($parent_node, $tag) = @_; 193154daed1Smrg local $node; 194154daed1Smrg 195154daed1Smrg if ($tag =~ /^\?.*/ || $tag =~ /^\!.*/) { 196154daed1Smrg $node = new_node($parent_node, $tag, 'COMMENT'); 197154daed1Smrg add_node($parent_node, $node); 198154daed1Smrg undef; return; 199154daed1Smrg } else { 200154daed1Smrg $node = new_node($parent_node, $tag, 'NODE'); 201154daed1Smrg $node->{CHILDREN} = []; 202154daed1Smrg add_node($parent_node, $node); 203154daed1Smrg return $node; 204154daed1Smrg } 205154daed1Smrg} 206154daed1Smrg 207154daed1Smrgsub add_text_node { 208154daed1Smrg local ($parent_node, $text) = @_; 209154daed1Smrg local $node = new_node($parent_node, $text, 'TEXT'); 210154daed1Smrg add_node($parent_node, $node); 211154daed1Smrg} 212154daed1Smrg 213154daed1Smrgsub node_by_name { 214154daed1Smrg local ($node, $name) = @_; 215154daed1Smrg local ($tagname, $path) = split(/\//, $name, 2); 216154daed1Smrg 217154daed1Smrg my @nodelist; 218154daed1Smrg 219154daed1Smrg if ($tagname eq '') { 220154daed1Smrg while ($node->{PARENT} != 0) { 221154daed1Smrg $node = $node->{PARENT}; 222154daed1Smrg } 223154daed1Smrg sublist_by_name($node, $path, \@nodelist); 224154daed1Smrg } else { 225154daed1Smrg sublist_by_name($node, $name, \@nodelist); 226154daed1Smrg } 227154daed1Smrg return @nodelist; 228154daed1Smrg} 229154daed1Smrg 230154daed1Smrgsub sublist_by_name { 231154daed1Smrg local ($node, $name, $res) = @_; 232154daed1Smrg local ($tagname, $path) = split(/\//, $name, 2); 233154daed1Smrg 234154daed1Smrg if (! defined $path) { 235154daed1Smrg push @{$res}, (@{$node->{$tagname}}); 236154daed1Smrg return; 237154daed1Smrg } 238154daed1Smrg 239154daed1Smrg if ($tagname eq '..' && $node->{PARENT} != 0) { 240154daed1Smrg $node = $node->{PARENT}; 241154daed1Smrg sublist_by_name($node, $path, $res); 242154daed1Smrg } else { 243154daed1Smrg local $n; 244154daed1Smrg for $n (@{$node->{$tagname}}) { 245154daed1Smrg sublist_by_name($n, $path, $res); 246154daed1Smrg } 247154daed1Smrg } 248154daed1Smrg} 249154daed1Smrg 250154daed1Smrgsub node_attribute { 251154daed1Smrg local $node = @_[0]; 252154daed1Smrg if (defined $node->{ATTRIBUTES}) { 253154daed1Smrg return $node->{ATTRIBUTES}{@_[1]}; 254154daed1Smrg } 255154daed1Smrg undef; 256154daed1Smrg} 257154daed1Smrg 258154daed1Smrgsub text_child { 259154daed1Smrg local ($node) = @_; 260154daed1Smrg local ($child) = node_by_name($node, 'TEXT'); 261154daed1Smrg return $child->{TEXT}; 262154daed1Smrg} 263