#!/opt/bin/perl # usage: res2pm open STDOUT, ">:utf8", "Deliantra/Data.pm" or die "Deliantra/Data.pm: $!"; print < for more info. =cut package Deliantra::Data; EOF use Data::Dumper; use XML::Grove::Builder; use XML::Parser::PerlSAX; sub dump_hash { my ($names, $refs) = @_; $d = new Data::Dumper ($refs, [map "*$_", @$names]); $d->Terse (1); $d->Indent (1); $d->Quotekeys (0); $d->Useqq (0); $d->Useperl(1); $d->Sortkeys (sub { [sort { $a > 0 && $b > 0 ? $a <=> $b : $a cmp $b } keys %{+shift}] }); my @vals = $d->Dump; while (@vals) { my $v = shift @vals; $v =~ s/^ /\t\t/gm; $v =~ s/^ /\t/gm; $v =~ s/\s+$//; my $name = shift @$names; my $ref = shift @$refs; my $sigil = ref $ref eq "ARRAY" ? '@' : '%'; print "our $sigil$name = $v;\n\n"; } } my $grove_builder = XML::Grove::Builder->new; my $parser = XML::Parser::PerlSAX->new ( Handler => $grove_builder ); my $type = $parser->parse ( Source => { SystemId => "res/types.xml" } ); my %bitmask; my %list; my %type; my %typename; my @attr0; my %attr; my %ignore_list; my %default_attr; my %spell; sub string($) { local $_ = join "", map $_->{Data}, @{shift->{Contents}}; $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ =~ s/\s+/ /g; $_ } sub parse_attr { my ($e, $sect) = @_; my $arch = { type => $e->{Attributes}->{type}, name => $e->{Attributes}->{editor}, desc => string $e, $e->{Attributes}->{arch_begin} ? (end => $e->{Attributes}->{arch_end}) : (), }; delete $arch->{name} unless defined $arch->{name}; delete $arch->{desc} unless length $arch->{desc}; if ($arch->{type} =~ s/^(bitmask)_(.*)/$1/) { $arch->{value} = $bitmask{$2} ||= {}; } elsif ($arch->{type} =~ s/^(list)_(.*)/$1/) { $arch->{value} = $list{$2} ||= {}; } elsif ($arch->{type} eq "fixed") { $arch->{value} = $e->{Attributes}->{value}; } elsif ($arch->{type} =~ s/^bool_special$/bool/) { $arch->{value} = [$e->{Attributes}->{false}, $e->{Attributes}->{true}]; } push @$sect, [$e->{Attributes}->{arch} || $e->{Attributes}->{arch_begin}, $arch]; } sub parse_type { my ($e, $type) = @_; my %main; for my $e (grep { $_->isa ('XML::Grove::Element') } @{$e->{Contents}}) { if ($e->{Name} eq "required") { # not used #for my $i (grep $_->isa ('XML::Grove::Element'), @{$e->{Contents}}) { # $type->{required}{$i->{Attributes}->{arch}} = $i->{Attributes}->{value}; #} } elsif ($e->{Name} eq "attribute") { parse_attr $e, $type->{attr} ||= []; } elsif ($e->{Name} eq "ignore") { for my $i (grep $_->isa ('XML::Grove::Element'), @{$e->{Contents}}) { if ($i->{Name} eq "ignore_list") { push @{$type->{ignore}}, $ignore_list{$i->{Attributes}->{name}} ||= []; } elsif ($i->{Name} eq "attribute") { warn "ACDD $i->{Attributes}->{arch}\n"; push @{$type->{ignore}}, [$i->{Attributes}->{arch}]; } } } elsif ($e->{Name} eq "import_type") { #push @{$type->{import}}, $type{$e->{Attributes}->{name}} ||= {}; push @{$type->{import}}, $e->{Attributes}->{name}; } elsif ($e->{Name} eq "use") { $type->{use} = string $e; } elsif ($e->{Name} eq "description") { $type->{desc} = string $e; } elsif ($e->{Name} eq "section") { my @attr; for my $i (grep $_->isa ('XML::Grove::Element'), @{$e->{Contents}}) { parse_attr $i, \@attr; } push @{ $type->{section} }, [$e->{Attributes}->{name} => \@attr]; } else { warn "unknown types subelement ", $e->{Name}; } } $type } for my $e (grep $_->isa ('XML::Grove::Element'), @{$type->root->{Contents}}) { if ($e->{Name} eq "bitmask") { my $bm = $bitmask{$e->{Attributes}->{name}} ||= {}; for my $b (grep $_->isa ('XML::Grove::Element'), @{$e->{Contents}}) { $bm->{$b->{Attributes}->{bit}} = $b->{Attributes}->{name}; } } elsif ($e->{Name} eq "list") { my $list = $list{$e->{Attributes}->{name}} ||= {}; for my $b (grep $_->isa ('XML::Grove::Element'), @{$e->{Contents}}) { $list->{$b->{Attributes}->{value}} = $b->{Attributes}->{name}; } } elsif ($e->{Name} eq "ignore_list") { my $list = $ignore_list{$e->{Attributes}->{name}} ||= []; for my $b (grep $_->isa ('XML::Grove::Element'), @{$e->{Contents}}) { push @$list, $b->{Attributes}->{arch}; } } elsif ($e->{Name} eq "default_type") { parse_type $e, \%default_attr; } elsif ($e->{Name} eq "type") { my $type = $type{$e->{Attributes}->{name}} ||= {}; $type->{name} = $e->{Attributes}->{name}; parse_type $e, $type; if ($e->{Attributes}->{number} > 0) { $attr{$e->{Attributes}->{number}} = $type; } elsif ($e->{Attributes}->{name} eq "Misc") { delete $type->{required}; } else { push @attr0, $type; } } else { warn "unknown types element ", $e->{Name}; } } my $type = $parser->parse ( Source => { SystemId => "res/typenumbers.xml" } ); for (grep $_->isa ('XML::Grove::Element'), @{$type->root->{Contents}}) { $typename{$_->{Attributes}->{number}} = $_->{Attributes}->{name}; } my $spell = $parser->parse ( Source => { SystemId => "res/spells.xml" } ) or die; for (grep $_->isa ('XML::Grove::Element'), @{$spell->root->{Contents}}) { $spell{$_->{Attributes}->{id}} = $_->{Attributes}->{name}; } dump_hash ["BITMASK", "LIST", "IGNORE_LIST", "DEFAULT_ATTR", "TYPE", "ATTR", "TYPENAME", "SPELL"], [\%bitmask, \%list, \%ignore_list, \%default_attr, \%type, \%attr, \%typename, \%spell]; print < http://home.schmorp.de/ The source files are part of the CFJavaEditor. =cut 1 EOF