#!/opt/bin/perl # usage: res2pm open STDOUT, ">:utf8", "Crossfire/Data.pm" or die "Crossfire/Data.pm: $!"; print < for more info. =cut package Crossfire::Data; EOF use Data::Dumper; use XML::Parser::Grove; 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 $type = XML::Parser->new (Style => 'grove')->parsefile ("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 "", @{shift->contents}; $_ =~ s/^\s+//; $_ =~ s/\s+$//; $_ =~ s/\s+/ /g; $_ } sub parse_attr { my ($e, $sect) = @_; my $arch = { type => $e->attr ("type"), name => $e->attr ("editor"), desc => string $e, $e->attr("arch_begin") ? (end => $e->attr("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} =~ s/^bool_special$/bool/) { $arch->{value} = [$e->attr ("false"), $e->attr ("true")]; } $sect->{$e->attr ("arch") || $e->attr("arch_begin")} = $arch; } sub parse_type { my ($e, $type) = @_; my %main; for my $e (grep ref, @{$e->contents}) { if ($e->name eq "required") { for my $i (grep ref, @{$e->contents}) { $type->{required}{$i->attr ("arch")} = $i->attr ("value"); } } elsif ($e->name eq "attribute") { parse_attr $e, $type->{attr} ||= {}; } elsif ($e->name eq "ignore") { for my $i (grep ref, @{$e->contents}) { if ($i->name eq "ignore_list") { push @{$type->{ignore}}, $ignore_list{$i->attr ("name")} ||= []; } elsif ($i->name eq "attribute") { push @{$type->{ignore}}, $i->attr ("arch"); } } } elsif ($e->name eq "import_type") { push @{$type->{import}}, $type{$e->attr ("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 ref, @{$e->contents}) { parse_attr $i, \%attr; } push @{ $type->{section} }, [$e->attr ("name") => \%attr]; } else { warn "unknown types subelement ", $e->name; } } $type } for my $e (grep ref, @{$type->root->contents}) { if ($e->name eq "bitmask") { my $bm = $bitmask{$e->attr ("name")} ||= {}; for my $b (grep ref, @{$e->contents}) { $bm->{$b->attr ("bit")} = $b->attr ("name"); } } elsif ($e->name eq "list") { my $list = $list{$e->attr ("name")} ||= {}; for my $b (grep ref, @{$e->contents}) { $list->{$b->attr ("value")} = $b->attr ("name"); } } elsif ($e->name eq "ignore_list") { my $list = $ignore_list{$e->attr ("name")} ||= []; for my $b (grep ref, @{$e->contents}) { push @$list, $b->attr ("arch"); } } elsif ($e->name eq "default_type") { parse_type $e, \%default_attr; } elsif ($e->name eq "type") { my $type = $type{$e->attr ("name")} ||= {}; $type->{name} = $e->attr ("name"); parse_type $e, $type; #unshift @{$type->{import}}, \%default_attr; if ($e->attr ("number") > 0) { $attr{$e->attr ("number")} = $type; } elsif ($e->attr ("name") eq "Misc") { delete $type->{required}; } else { push @attr0, $type; } } else { warn "unknown types element ", $e->name; } } my $type = XML::Parser->new (Style => 'grove')->parsefile ("res/typenumbers.xml"); for (grep ref, @{$type->root->contents}) { $typename{$_->attr ("number")} = $_->attr ("name"); } my $spell = XML::Parser->new (Style => 'grove')->parsefile ("res/spells.xml") or die; for (grep ref, @{$spell->root->contents}) { $spell{$_->attr ("id")} = $_->attr ("name"); } dump_hash ["BITMASK", "LIST", "IGNORE_LIST", "DEFAULT_ATTR", "TYPE", "ATTR0", "ATTR", "TYPENAME", "SPELL"], [\%bitmask, \%list, \%ignore_list, \%default_attr, \%type, \@attr0, \%attr, \%typename, \%spell]; print < http://home.schmorp.de/ The source files are part of the CFJavaEditor. =cut 1 EOF