31 $VERSION = 1.00; |
31 $VERSION = 1.00; |
32 @ISA = qw(Exporter); |
32 @ISA = qw(Exporter); |
33 @EXPORT = qw(&obyparse_info &obyparse_init &obyparse_process); |
33 @EXPORT = qw(&obyparse_info &obyparse_init &obyparse_process); |
34 } |
34 } |
35 |
35 |
36 my $conf = ""; |
36 my $conf; |
37 |
37 |
38 sub obyparse_info() |
38 sub obyparse_info() |
39 { |
39 { |
40 return({ |
40 return({ |
41 name => "obyparse", |
41 name => "obyparse", |
42 invocation => "InvocationPoint2", |
42 invocation => "InvocationPoint2", # tmp6.oby |
43 initialize => "obyparse::obyparse_init", |
43 initialize => "obyparse::obyparse_init", |
44 single => "obyparse::obyparse_process"}); |
44 single => "obyparse::obyparse_process"}); |
45 } |
45 } |
46 |
46 |
47 sub obyparse_init($) |
47 sub obyparse_init($) |
48 { |
48 { |
49 plugin_init("obyparse.pm", $conf = shift()); |
49 plugin_init(&obyparse_info, $conf = shift(), 0); |
50 } |
50 } |
51 |
51 |
52 sub obyparse_readconffile($$$$$); |
52 sub obyparse_readconffile($$$$$); |
53 |
53 sub obyparse_findincfiles(); |
|
54 sub obyparse_findspifiles(); |
54 |
55 |
55 sub obyparse_process($) |
56 sub obyparse_process($) |
56 { |
57 { |
57 plugin_start("obyparse.pm", $conf); |
58 plugin_start(&obyparse_info, $conf); |
58 |
59 |
59 my $obydata = shift(); |
60 my ($obydata, $romfiles, $rofs1files, $udebfiles, $urelfiles, $fname) = (shift(), undef, undef, "", "", ""); |
60 my %targets = (); |
61 my %targets = my %patchdata = (); |
61 my %patchdata = (); |
62 |
62 my ($romfiles, $rofs1files, $udebfiles, $urelfiles) = (undef, undef, "", ""); |
63 obyparse_findincfiles(); |
63 my $fname = ""; |
64 obyparse_findspifiles(); |
|
65 plugin_reset(); |
64 |
66 |
65 foreach (@$obydata) |
67 foreach (@$obydata) |
66 { |
68 { |
67 next if (my $parse = parse_obyline($_)) < 0; |
69 next if !(my $parse = parse_obyline($_)); |
68 |
70 |
69 if (($parse == 1) && ($gKeyword =~ FILEBITMAPSPECKEYWORD)) { |
71 if (($parse == 2) && ($gKeyword =~ FILEBITMAPSPECKEYWORD)) { |
70 ($fname = lc($gTarget)) =~ /^(?:.*\\)?(.+?)$/; |
72 $targets{$gTgtCmp} = $targets{File::Basename::basename($gTgtCmp)} = [$gLnum - 1, |
71 my $tname = $1; |
73 !$gRomid && ($gKeyword =~ ROFSBITMAPFILESPECKEYWORD) && ($gAttrib !~ /paging_unmovable/i)] |
72 $targets{$fname} = $targets{$tname} = [$gLnum - 1, !$gRomid && ($gKeyword =~ ROFSBITMAPFILESPECKEYWORD)]; |
74 if ($gImgid == $gRomidCmp); |
|
75 dprint(2, "Removed attribute paging_unmovable: `$_'") |
|
76 if ($gAttrib =~ /paging_unmovable/i) && (s/\s+paging_unmovable\s*(?=\s|^)//i); |
73 next; |
77 next; |
74 } |
78 } |
75 |
79 |
76 next if !/^\s*OBYPARSE_(ROM|ROFS1|UDEB|UREL)\s+(.+?)\s*$/i; |
80 next if !/^\s*OBYPARSE_(ROM|ROFS1|UDEB|UREL)\s+(.+?)\s*$/i; |
77 |
81 |
78 (my $rule, $fname) = (uc($1), $2); |
82 (my $rule, $fname) = (uc($1), $2); |
|
83 $_ = "$gHandlestr $_"; |
|
84 next if $gRomid && ($gImgid != $gRomidCmp); |
|
85 |
|
86 dprint(2, "#$gLnum: `$gLine'"); |
79 my $files = ($rule eq "ROM" ? \$romfiles : ($rule eq "ROFS1" ? \$rofs1files : |
87 my $files = ($rule eq "ROM" ? \$romfiles : ($rule eq "ROFS1" ? \$rofs1files : |
80 ($rule eq "UDEB" ? \$udebfiles : \$urelfiles))); |
88 ($rule eq "UDEB" ? \$udebfiles : \$urelfiles))); |
81 $$files = "" if !defined($$files); |
89 $$files = "" if !defined($$files); |
82 dprint(2, "#$gLnum: `$gLine'"); |
|
83 |
90 |
84 if ($fname ne "*") { |
91 if ($fname ne "*") { |
85 my $basedir = ""; |
92 my $basedir = ""; |
86 ($basedir, $fname) = ($1, $2) if $fname =~ /^(.*[\/\\])(.+?)$/; |
93 ($basedir, $fname) = ($1, $2) if $fname =~ /^(.*[\/\\])(.+?)$/; |
87 dprint(3, "Found " . obyparse_readconffile($basedir, $fname, $rule, $files, 0) . " entries"); |
94 dprint(3, "Found " . obyparse_readconffile($basedir, $fname, $rule, $files, 0) . " entries"); |
88 } |
95 } else { |
89 else { |
96 dprint(3, "Move/change all possible components to $rule"); |
90 $$files = ".*"; |
97 $$files = ".*"; |
91 dprint(3, "Move/change all possible components to $rule"); |
98 } |
92 } |
|
93 $_ = "$gHandlestr $_"; |
|
94 } |
99 } |
95 |
100 |
96 $romfiles = qr/^($romfiles)$/i if defined($romfiles); |
101 $romfiles = qr/^($romfiles)$/i if defined($romfiles); |
97 $rofs1files = qr/^($rofs1files)$/i if defined($rofs1files); |
102 $rofs1files = qr/^($rofs1files)$/i if defined($rofs1files); |
98 ($udebfiles, $urelfiles) = (qr/^($udebfiles)$/i, qr/^($urelfiles)$/i); |
103 ($udebfiles, $urelfiles) = (qr/^($udebfiles)$/i, qr/^($urelfiles)$/i); |
99 |
104 |
100 ($gLnum, $gRomid) = (0, 0); |
105 my ($rofs1ofs, $udebcnt, $urelcnt, @torofs1) = (0, 0, 0, ()); |
101 my ($rofs1cnt, $udebcnt, $urelcnt, $offset, @torofs1) = (0, 0, 0, 0, ()); |
106 plugin_reset(); |
102 |
107 |
103 foreach (@$obydata) |
108 foreach (@$obydata) |
104 { |
109 { |
105 my $parse = parse_obyline($_); |
110 my $parse = parse_obyline($_); |
106 $offset++ if $gRomid < 2; |
111 $rofs1ofs++ if ($gRomid < 2); |
107 next if $parse != 1; |
112 next if ($parse != 2) || ($gImgid != $gRomidCmp); |
108 |
113 |
109 if ($gKeyword =~ /^patchdata$/i) { |
114 if ($gKeyword =~ /^patchdata$/i) { |
110 $gSource =~ /^(.+?)(?:@.+)?$/; |
115 $gSrcCmp =~ /^(.+?)(?:@.+)?$/; |
111 $fname = lc($1); |
116 next if !exists($targets{$fname = $1}); |
112 $patchdata{$fname} = $targets{$fname}[0] if !exists($patchdata{$fname}); |
117 $patchdata{$fname} = $targets{$fname}[0] if !exists($patchdata{$fname}); |
113 } |
118 next if !$targets{$fname}[1]; |
114 else { |
119 } |
115 $gTarget =~ /^(?:.*\\)?(.+?)$/; |
120 elsif ($gKeyword =~ FILEBITMAPSPECKEYWORD) { |
116 $fname = $1; |
121 $fname = File::Basename::basename($gTgtCmp); |
117 if ($fname =~ $urelfiles && s/(?<=[\/\\])udeb(?=[\/\\])/urel/i) { |
122 if ($fname =~ $urelfiles && s/(?<=[\/\\])udeb(?=[\/\\])/urel/i) { |
118 $urelcnt++; |
123 $urelcnt++; |
119 dprint(2, "Changed to UREL: `$_'"); |
124 dprint(2, "Changed to UREL: `$_'"); |
120 } |
125 } |
121 elsif ($fname =~ $udebfiles && s/(?<=[\/\\])urel(?=[\/\\])/udeb/i) { |
126 elsif ($fname =~ $udebfiles && s/(?<=[\/\\])urel(?=[\/\\])/udeb/i) { |
122 $udebcnt++; |
127 $udebcnt++; |
123 dprint(2, "Changed to UDEB: `$_'"); |
128 dprint(2, "Changed to UDEB: `$_'"); |
124 } |
129 } |
125 } |
130 next if !$targets{$gTgtCmp}[1]; |
126 |
131 } |
127 next if $gRomid || !defined($romfiles) && !defined($rofs1files); |
132 elsif ($gKeyword =~ DIRECTORYKEYWORD) { |
128 |
133 $fname = File::Basename::basename($gTgtCmp); |
129 if (($gKeyword =~ ROFSBITMAPFILESPECKEYWORD) || |
134 next if !(exists($targets{$gTgtCmp}) && $targets{$gTgtCmp}[1]) && |
130 ($gKeyword =~ /^patchdata$/i) && exists($targets{$fname}) && $targets{$fname}[1]) { |
135 !(exists($targets{$fname}) && $targets{$fname}[1]); |
131 } |
136 } |
132 elsif ($gKeyword =~ /^(?:alias|rename)/i && exists($targets{lc($gSource)}) && $targets{lc($gSource)}[1]) { |
137 else { next } |
133 $gSource =~ /^(?:.*\\)?(.+?)$/; |
138 |
134 $fname = $1; |
139 if (!$gRomid && (defined($rofs1files) && ($fname =~ $rofs1files) || defined($romfiles) && ($fname !~ $romfiles))) { |
135 } |
|
136 else { |
|
137 next; |
|
138 } |
|
139 if (defined($rofs1files) && ($fname =~ $rofs1files) || defined($romfiles) && ($fname !~ $romfiles)) { |
|
140 $rofs1cnt++; |
|
141 push(@torofs1, $_); |
140 push(@torofs1, $_); |
142 $_ = "$gHandlestr =>ROFS1 $_"; |
141 $_ = "$gHandlestr $_"; |
143 } |
142 } |
144 } |
143 } |
145 |
144 |
146 dprint(3, "Moved $rofs1cnt entries to ROFS1") if $rofs1cnt; |
145 dprint(3, "Moved " . scalar(@torofs1) . " entries to ROFS1") if @torofs1; |
147 dprint(3, "Changed $udebcnt components to UDEB") if $udebcnt; |
146 dprint(3, "Changed $udebcnt components to UDEB") if $udebcnt; |
148 dprint(3, "Changed $urelcnt components to UREL") if $urelcnt; |
147 dprint(3, "Changed $urelcnt components to UREL") if $urelcnt; |
149 |
148 |
150 dprint(2, "Found " . keys(%patchdata) . " ROM-patched components:") if %patchdata; |
149 dprint(3, "Finding ROM-patched components"); |
151 foreach (sort({$a <=> $b} values(%patchdata))) { |
150 foreach (sort({$a <=> $b} values(%patchdata))) { |
152 ${$obydata}[$_] =~ /^(?:$gHandlestr =>ROFS1 )?(.+)$/; |
151 ${$obydata}[$_] =~ /^(?:$gHandlestr )?(.+)$/; |
153 parse_keyline($1); |
152 parse_keyline($1); |
154 dprint(2, "`$gSource'"); |
153 dprint(2, "`$gSource'"); |
155 } |
154 } |
156 |
155 dprint(3, "Found " . keys(%patchdata) . " ROM-patched components"); |
157 splice(@$obydata, $offset, 0, @torofs1) if @torofs1; |
156 |
|
157 splice(@$obydata, $rofs1ofs, 0, @torofs1) if @torofs1; |
158 |
158 |
159 plugin_end(); |
159 plugin_end(); |
160 } |
160 } |
161 |
161 |
|
162 sub obyparse_findincfiles() |
|
163 { |
|
164 my ($drive, $indent, $prev, $tmpoby, %files) = |
|
165 (Cwd::cwd() =~ /^([a-z]:)/i ? $1 : "", -2, "", "$gWorkdir/tmp1.oby", ()); |
|
166 |
|
167 dprint(3, "Finding include hierarchy from `$tmpoby'"); |
|
168 open(FILE, $tmpoby) or dprint(-3, "$gPluginname can't open `$tmpoby'"), return; |
|
169 |
|
170 while (my $line = <FILE>) { |
|
171 next if ($line !~ /^#\s+\d+\s+"(.+?)"(?:\s+(\d))?$/); |
|
172 my ($file, $flag) = ($1, defined($2) ? $2 : 0); |
|
173 next if ($file =~ /^<.*>$/); |
|
174 $indent -= 2, $prev = $file, next if ($flag == 2); |
|
175 next if (!$flag && $file eq $prev || $flag > 1); |
|
176 $indent += 2 if $flag; |
|
177 ($prev = $file) =~ /^(.*[\/\\])?(.+?)$/; |
|
178 (my $dir, $file) = ("", $2); |
|
179 $dir = abspath(defined($1) ? $1 : "."); |
|
180 dprint(2, ("." x $indent) . "`$prev' !!!"), next if ($dir eq ""); |
|
181 $dir =~ s/^$drive|\/$//gi; |
|
182 $files{lc($file = "$dir/$file")} = 1; |
|
183 dprint(2, ("." x $indent) . "`$file'"); |
|
184 } |
|
185 close(FILE); |
|
186 dprint(3, "Found " . keys(%files) . " different include files"); |
|
187 } |
|
188 |
|
189 sub obyparse_findspifiles() |
|
190 { |
|
191 my ($spicnt, $tmpoby) = (0, "$gWorkdir/tmp5.oby"); |
|
192 |
|
193 dprint(3, "Finding SPI input files from `$tmpoby'"); |
|
194 open(FILE, $tmpoby) or dprint(-3, "$gPluginname can't open `$tmpoby'"), return; |
|
195 |
|
196 while (my $line = <FILE>) { |
|
197 next if (parse_obyline($line) != 2) || ($gKeyword !~ /^spidata/i); |
|
198 $spicnt++; |
|
199 dprint(2, "`$gSource'" . ($gKeyword =~ /^spidata$/i ? "" : " ($gKeyword)")); |
|
200 } |
|
201 close(FILE); |
|
202 dprint(3, "Found $spicnt SPI input files"); |
|
203 } |
162 |
204 |
163 sub obyparse_readconffile($$$$$) |
205 sub obyparse_readconffile($$$$$) |
164 { |
206 { |
165 my ($basedir, $file, $type, $files, $indent) = @_; |
207 my ($basedir, $file, $type, $files, $indent) = @_; |
166 $file = $basedir . $file; |
208 $file = "$basedir$file"; |
167 my $filecnt = 0; |
209 my $filecnt = 0; |
168 |
210 |
169 dprint(3, "Reading $type files") if $type; |
211 dprint(3, "Reading $type files from $file") if $type; |
170 dprint(3, ("." x $indent) . "`$file'"); |
212 dprint(2, ("." x $indent) . "`$file'"); |
171 |
213 |
172 open(FILE, $file) or die("ERROR: Can't open `$file'\n"); |
214 open(FILE, $file) or dprint(3, "Error: $gPluginname can't open $file", 1), die("\n"); |
173 |
215 my @files = <FILE>; |
174 foreach my $line (<FILE>) { |
216 close(FILE); |
175 if ($line =~ /^\s*#include\s+(.+?)\s*$/i) { |
217 |
|
218 foreach (@files) { |
|
219 if (/^\s*#include\s+(.+?)\s*$/i) { |
176 $filecnt += obyparse_readconffile($basedir, $1, "", $files, $indent + 2); |
220 $filecnt += obyparse_readconffile($basedir, $1, "", $files, $indent + 2); |
177 next; |
221 next; |
178 } |
222 } |
179 next if ($line =~ /^\s*$/) || ($line =~ /^\s*(?:#|\/\/|REM\s)/i); |
223 next if (/^\s*$/) || (/^\s*(?:#|\/\/|REM\s)/i); |
180 $filecnt++; |
224 $filecnt++; |
181 (my $fname = $line) =~ s/^\s+|\s+$//g; |
225 (my $fname = $_) =~ s/^\s+|\s+$//g; |
182 $fname =~ s/(.)/{'*' => '.*', '?' => '.', '[' => '[', ']' => ']'}->{$1} || "\Q$1\E"/ge; |
226 $fname =~ s/(.)/{"*" => ".*", "?" => "."}->{$1} || "\Q$1\E"/eg; |
183 $$files .= ($$files eq "" ? "" : "|") . $fname; |
227 $$files .= ($$files eq "" ? "" : "|") . $fname; |
184 } |
228 } |
185 close(FILE); |
|
186 return($filecnt); |
229 return($filecnt); |
187 } |
230 } |
188 |
231 |
189 1; |
232 1; |
190 |
233 |