| 1 |
#!/opt/bin/perl |
| 2 |
|
| 3 |
# usage: res2pm |
| 4 |
|
| 5 |
open STDOUT, ">:utf8", "Crossfire/Data.pm" |
| 6 |
or die "Crossfire/Data.pm: $!"; |
| 7 |
|
| 8 |
print <<EOF; |
| 9 |
=head1 NAME |
| 10 |
|
| 11 |
Crossfire::Data - various data structures useful for understanding archs and objects |
| 12 |
|
| 13 |
=head1 |
| 14 |
|
| 15 |
THIS FILE IS AUTOGENERATED, DO NOT EDIT! |
| 16 |
|
| 17 |
It's a translation of the following files: |
| 18 |
|
| 19 |
res/spells.xml |
| 20 |
res/types.xml |
| 21 |
res/typenumbers.xml |
| 22 |
|
| 23 |
See F<res/README> for more info. |
| 24 |
|
| 25 |
=cut |
| 26 |
|
| 27 |
package Crossfire::Data; |
| 28 |
|
| 29 |
EOF |
| 30 |
|
| 31 |
use Data::Dumper; |
| 32 |
use XML::Parser::Grove; |
| 33 |
|
| 34 |
sub dump_hash { |
| 35 |
my ($names, $refs) = @_; |
| 36 |
|
| 37 |
$d = new Data::Dumper ($refs, [map "*$_", @$names]); |
| 38 |
$d->Terse (1); |
| 39 |
$d->Indent (1); |
| 40 |
$d->Quotekeys (0); |
| 41 |
$d->Useqq (0); |
| 42 |
$d->Useperl(1); |
| 43 |
$d->Sortkeys (sub { |
| 44 |
[sort { |
| 45 |
$a > 0 && $b > 0 ? $a <=> $b |
| 46 |
: $a cmp $b |
| 47 |
} keys %{+shift}] |
| 48 |
}); |
| 49 |
|
| 50 |
my @vals = $d->Dump; |
| 51 |
|
| 52 |
while (@vals) { |
| 53 |
my $v = shift @vals; |
| 54 |
$v =~ s/^ /\t\t/gm; |
| 55 |
$v =~ s/^ /\t/gm; |
| 56 |
$v =~ s/\s+$//; |
| 57 |
|
| 58 |
my $name = shift @$names; |
| 59 |
my $ref = shift @$refs; |
| 60 |
|
| 61 |
my $sigil = ref $ref eq "ARRAY" ? '@' : '%'; |
| 62 |
|
| 63 |
print "our $sigil$name = $v;\n\n"; |
| 64 |
} |
| 65 |
} |
| 66 |
|
| 67 |
my $type = XML::Parser->new (Style => 'grove')->parsefile ("res/types.xml"); |
| 68 |
|
| 69 |
my %bitmask; |
| 70 |
my %list; |
| 71 |
my %type; |
| 72 |
my %typename; |
| 73 |
my @attr0; |
| 74 |
my %attr; |
| 75 |
my %ignore_list; |
| 76 |
my %default_attr; |
| 77 |
my %spell; |
| 78 |
|
| 79 |
sub string($) { |
| 80 |
local $_ = join "", @{shift->contents}; |
| 81 |
$_ =~ s/^\s+//; |
| 82 |
$_ =~ s/\s+$//; |
| 83 |
$_ =~ s/\s+/ /g; |
| 84 |
$_ |
| 85 |
} |
| 86 |
|
| 87 |
sub parse_attr { |
| 88 |
my ($e, $sect) = @_; |
| 89 |
|
| 90 |
my $arch = { |
| 91 |
type => $e->attr ("type"), |
| 92 |
name => $e->attr ("editor"), |
| 93 |
desc => string $e, |
| 94 |
$e->attr("arch_begin") ? (end => $e->attr("arch_end")) : (), |
| 95 |
}; |
| 96 |
|
| 97 |
delete $arch->{name} unless defined $arch->{name}; |
| 98 |
delete $arch->{desc} unless length $arch->{desc}; |
| 99 |
|
| 100 |
if ($arch->{type} =~ s/^(bitmask)_(.*)/$1/) { |
| 101 |
$arch->{value} = $bitmask{$2} ||= {}; |
| 102 |
} elsif ($arch->{type} =~ s/^(list)_(.*)/$1/) { |
| 103 |
$arch->{value} = $list{$2} ||= {}; |
| 104 |
} elsif ($arch->{type} eq "fixed") { |
| 105 |
$arch->{value} = $e->attr ("value"); |
| 106 |
} elsif ($arch->{type} =~ s/^bool_special$/bool/) { |
| 107 |
$arch->{value} = [$e->attr ("false"), $e->attr ("true")]; |
| 108 |
} |
| 109 |
|
| 110 |
push @$sect, [$e->attr ("arch") || $e->attr("arch_begin"), $arch]; |
| 111 |
} |
| 112 |
|
| 113 |
sub parse_type { |
| 114 |
my ($e, $type) = @_; |
| 115 |
|
| 116 |
my %main; |
| 117 |
|
| 118 |
for my $e (grep ref, @{$e->contents}) { |
| 119 |
if ($e->name eq "required") { |
| 120 |
# not used |
| 121 |
#for my $i (grep ref, @{$e->contents}) { |
| 122 |
# $type->{required}{$i->attr ("arch")} = $i->attr ("value"); |
| 123 |
#} |
| 124 |
} elsif ($e->name eq "attribute") { |
| 125 |
parse_attr $e, $type->{attr} ||= []; |
| 126 |
} elsif ($e->name eq "ignore") { |
| 127 |
for my $i (grep ref, @{$e->contents}) { |
| 128 |
if ($i->name eq "ignore_list") { |
| 129 |
push @{$type->{ignore}}, $ignore_list{$i->attr ("name")} ||= []; |
| 130 |
} elsif ($i->name eq "attribute") { |
| 131 |
push @{$type->{ignore}}, $i->attr ("arch"); |
| 132 |
} |
| 133 |
} |
| 134 |
} elsif ($e->name eq "import_type") { |
| 135 |
push @{$type->{import}}, $type{$e->attr ("name")} ||= {}; |
| 136 |
} elsif ($e->name eq "use") { |
| 137 |
$type->{use} = string $e; |
| 138 |
} elsif ($e->name eq "description") { |
| 139 |
$type->{desc} = string $e; |
| 140 |
} elsif ($e->name eq "section") { |
| 141 |
my @attr; |
| 142 |
for my $i (grep ref, @{$e->contents}) { |
| 143 |
parse_attr $i, \@attr; |
| 144 |
} |
| 145 |
push @{ $type->{section} }, [$e->attr ("name") => \@attr]; |
| 146 |
} else { |
| 147 |
warn "unknown types subelement ", $e->name; |
| 148 |
} |
| 149 |
} |
| 150 |
|
| 151 |
$type |
| 152 |
} |
| 153 |
|
| 154 |
for my $e (grep ref, @{$type->root->contents}) { |
| 155 |
if ($e->name eq "bitmask") { |
| 156 |
my $bm = $bitmask{$e->attr ("name")} ||= {}; |
| 157 |
for my $b (grep ref, @{$e->contents}) { |
| 158 |
$bm->{$b->attr ("bit")} = $b->attr ("name"); |
| 159 |
} |
| 160 |
} elsif ($e->name eq "list") { |
| 161 |
my $list = $list{$e->attr ("name")} ||= {}; |
| 162 |
for my $b (grep ref, @{$e->contents}) { |
| 163 |
$list->{$b->attr ("value")} = $b->attr ("name"); |
| 164 |
} |
| 165 |
} elsif ($e->name eq "ignore_list") { |
| 166 |
my $list = $ignore_list{$e->attr ("name")} ||= []; |
| 167 |
for my $b (grep ref, @{$e->contents}) { |
| 168 |
push @$list, $b->attr ("arch"); |
| 169 |
} |
| 170 |
} elsif ($e->name eq "default_type") { |
| 171 |
parse_type $e, \%default_attr; |
| 172 |
} elsif ($e->name eq "type") { |
| 173 |
my $type = $type{$e->attr ("name")} ||= {}; |
| 174 |
|
| 175 |
$type->{name} = $e->attr ("name"); |
| 176 |
|
| 177 |
parse_type $e, $type; |
| 178 |
|
| 179 |
if ($e->attr ("number") > 0) { |
| 180 |
$attr{$e->attr ("number")} = $type; |
| 181 |
} elsif ($e->attr ("name") eq "Misc") { |
| 182 |
delete $type->{required}; |
| 183 |
} else { |
| 184 |
push @attr0, $type; |
| 185 |
} |
| 186 |
|
| 187 |
} else { |
| 188 |
warn "unknown types element ", $e->name; |
| 189 |
} |
| 190 |
} |
| 191 |
|
| 192 |
my $type = XML::Parser->new (Style => 'grove')->parsefile ("res/typenumbers.xml"); |
| 193 |
|
| 194 |
for (grep ref, @{$type->root->contents}) { |
| 195 |
$typename{$_->attr ("number")} = $_->attr ("name"); |
| 196 |
} |
| 197 |
|
| 198 |
my $spell = XML::Parser->new (Style => 'grove')->parsefile ("res/spells.xml") |
| 199 |
or die; |
| 200 |
|
| 201 |
for (grep ref, @{$spell->root->contents}) { |
| 202 |
$spell{$_->attr ("id")} = $_->attr ("name"); |
| 203 |
} |
| 204 |
|
| 205 |
dump_hash ["BITMASK", "LIST", "IGNORE_LIST", "DEFAULT_ATTR", "TYPE", "ATTR", "TYPENAME", "SPELL"], |
| 206 |
[\%bitmask, \%list, \%ignore_list, \%default_attr, \%type, \%attr, \%typename, \%spell]; |
| 207 |
|
| 208 |
print <<EOF; |
| 209 |
|
| 210 |
=head1 AUTHOR |
| 211 |
|
| 212 |
Marc Lehmann <schmorp@schmorp.de> |
| 213 |
http://home.schmorp.de/ |
| 214 |
|
| 215 |
The source files are part of the CFJavaEditor. |
| 216 |
|
| 217 |
=cut |
| 218 |
|
| 219 |
1 |
| 220 |
EOF |
| 221 |
|