imgtools/imaker/buildrom_plugins/obyparse.pm
changeset 607 378360dbbdba
parent 596 9f25be3da657
--- a/imgtools/imaker/buildrom_plugins/obyparse.pm	Wed Jun 23 17:27:59 2010 +0800
+++ b/imgtools/imaker/buildrom_plugins/obyparse.pm	Wed Jun 30 11:35:58 2010 +0800
@@ -33,87 +33,92 @@
     @EXPORT  = qw(&obyparse_info &obyparse_init &obyparse_process);
 }
 
-my $conf = "";
+my $conf;
 
 sub obyparse_info()
 {
     return({
         name       => "obyparse",
-        invocation => "InvocationPoint2",
+        invocation => "InvocationPoint2",  # tmp6.oby
         initialize => "obyparse::obyparse_init",
         single     => "obyparse::obyparse_process"});
 }
 
 sub obyparse_init($)
 {
-    plugin_init("obyparse.pm", $conf = shift());
+    plugin_init(&obyparse_info, $conf = shift(), 0);
 }
 
 sub obyparse_readconffile($$$$$);
-
+sub obyparse_findincfiles();
+sub obyparse_findspifiles();
 
 sub obyparse_process($)
 {
-    plugin_start("obyparse.pm", $conf);
+    plugin_start(&obyparse_info, $conf);
 
-    my $obydata = shift();
-    my %targets = ();
-    my %patchdata = ();
-    my ($romfiles, $rofs1files, $udebfiles, $urelfiles) = (undef, undef, "", "");
-    my $fname = "";
+    my ($obydata, $romfiles, $rofs1files, $udebfiles, $urelfiles, $fname) = (shift(), undef, undef, "", "", "");
+    my %targets = my %patchdata = ();
+
+    obyparse_findincfiles();
+    obyparse_findspifiles();
+    plugin_reset();
 
     foreach (@$obydata)
     {
-        next if (my $parse = parse_obyline($_)) < 0;
+        next if !(my $parse = parse_obyline($_));
 
-        if (($parse == 1) && ($gKeyword =~ FILEBITMAPSPECKEYWORD)) {
-            ($fname = lc($gTarget)) =~ /^(?:.*\\)?(.+?)$/;
-            my $tname = $1;
-            $targets{$fname} = $targets{$tname} = [$gLnum - 1, !$gRomid && ($gKeyword =~ ROFSBITMAPFILESPECKEYWORD)];
+        if (($parse == 2) && ($gKeyword =~ FILEBITMAPSPECKEYWORD)) {
+            $targets{$gTgtCmp} = $targets{File::Basename::basename($gTgtCmp)} = [$gLnum - 1,
+                !$gRomid && ($gKeyword =~ ROFSBITMAPFILESPECKEYWORD) && ($gAttrib !~ /paging_unmovable/i)]
+                    if ($gImgid == $gRomidCmp);
+            dprint(2, "Removed attribute paging_unmovable: `$_'")
+                if ($gAttrib =~ /paging_unmovable/i) && (s/\s+paging_unmovable\s*(?=\s|^)//i);
             next;
         }
 
         next if !/^\s*OBYPARSE_(ROM|ROFS1|UDEB|UREL)\s+(.+?)\s*$/i;
 
         (my $rule, $fname) = (uc($1), $2);
+        $_ = "$gHandlestr $_";
+        next if $gRomid && ($gImgid != $gRomidCmp);
+
+        dprint(2, "#$gLnum: `$gLine'");
         my $files = ($rule eq "ROM" ? \$romfiles : ($rule eq "ROFS1" ? \$rofs1files :
             ($rule eq "UDEB" ? \$udebfiles : \$urelfiles)));
         $$files = "" if !defined($$files);
-        dprint(2, "#$gLnum: `$gLine'");
 
         if ($fname ne "*") {
             my $basedir = "";
             ($basedir, $fname) = ($1, $2) if $fname =~ /^(.*[\/\\])(.+?)$/;
             dprint(3, "Found " . obyparse_readconffile($basedir, $fname, $rule, $files, 0) . " entries");
-        }
-        else {
+        } else {
+            dprint(3, "Move/change all possible components to $rule");
             $$files = ".*";
-            dprint(3, "Move/change all possible components to $rule");
         }
-        $_ = "$gHandlestr $_";
     }
 
     $romfiles   = qr/^($romfiles)$/i   if defined($romfiles);
     $rofs1files = qr/^($rofs1files)$/i if defined($rofs1files);
     ($udebfiles, $urelfiles) = (qr/^($udebfiles)$/i, qr/^($urelfiles)$/i);
 
-    ($gLnum, $gRomid) = (0, 0);
-    my ($rofs1cnt, $udebcnt, $urelcnt, $offset, @torofs1) = (0, 0, 0, 0, ());
+    my ($rofs1ofs, $udebcnt, $urelcnt, @torofs1) = (0, 0, 0, ());
+    plugin_reset();
 
     foreach (@$obydata)
     {
         my $parse = parse_obyline($_);
-        $offset++ if $gRomid < 2;
-        next if $parse != 1;
+        $rofs1ofs++ if ($gRomid < 2);
+        next if ($parse != 2) || ($gImgid != $gRomidCmp);
 
         if ($gKeyword =~ /^patchdata$/i) {
-            $gSource =~ /^(.+?)(?:@.+)?$/;
-            $fname = lc($1);
+            $gSrcCmp =~ /^(.+?)(?:@.+)?$/;
+            next if !exists($targets{$fname = $1});
             $patchdata{$fname} = $targets{$fname}[0] if !exists($patchdata{$fname});
+            next if !$targets{$fname}[1];
         }
-        else {
-            $gTarget =~ /^(?:.*\\)?(.+?)$/;
-            $fname = $1;
+        elsif ($gKeyword =~ FILEBITMAPSPECKEYWORD) {
+            $fname = File::Basename::basename($gTgtCmp);
             if ($fname =~ $urelfiles && s/(?<=[\/\\])udeb(?=[\/\\])/urel/i) {
                 $urelcnt++;
                 dprint(2, "Changed to UREL: `$_'");
@@ -122,67 +127,105 @@
                 $udebcnt++;
                 dprint(2, "Changed to UDEB: `$_'");
             }
-        }
-
-        next if $gRomid || !defined($romfiles) && !defined($rofs1files);
-
-        if (($gKeyword =~ ROFSBITMAPFILESPECKEYWORD) ||
-            ($gKeyword =~ /^patchdata$/i) && exists($targets{$fname}) && $targets{$fname}[1]) {
+            next if !$targets{$gTgtCmp}[1];
         }
-        elsif ($gKeyword =~ /^(?:alias|rename)/i && exists($targets{lc($gSource)}) && $targets{lc($gSource)}[1]) {
-            $gSource =~ /^(?:.*\\)?(.+?)$/;
-            $fname = $1;
+        elsif ($gKeyword =~ DIRECTORYKEYWORD) {
+            $fname = File::Basename::basename($gTgtCmp);
+            next if !(exists($targets{$gTgtCmp}) && $targets{$gTgtCmp}[1]) &&
+                !(exists($targets{$fname}) && $targets{$fname}[1]);
         }
-        else {
-            next;
-        }
-        if (defined($rofs1files) && ($fname =~ $rofs1files) || defined($romfiles) && ($fname !~ $romfiles)) {
-            $rofs1cnt++;
+        else { next }
+
+        if (!$gRomid && (defined($rofs1files) && ($fname =~ $rofs1files) || defined($romfiles) && ($fname !~ $romfiles))) {
             push(@torofs1, $_);
-            $_ = "$gHandlestr =>ROFS1 $_";
+            $_ = "$gHandlestr $_";
         }
     }
 
-    dprint(3, "Moved $rofs1cnt entries to ROFS1")    if $rofs1cnt;
+    dprint(3, "Moved " . scalar(@torofs1) . " entries to ROFS1") if @torofs1;
     dprint(3, "Changed $udebcnt components to UDEB") if $udebcnt;
     dprint(3, "Changed $urelcnt components to UREL") if $urelcnt;
 
-    dprint(2, "Found " . keys(%patchdata) . " ROM-patched components:") if %patchdata;
+    dprint(3, "Finding ROM-patched components");
     foreach (sort({$a <=> $b} values(%patchdata))) {
-        ${$obydata}[$_] =~ /^(?:$gHandlestr =>ROFS1 )?(.+)$/;
+        ${$obydata}[$_] =~ /^(?:$gHandlestr )?(.+)$/;
         parse_keyline($1);
         dprint(2, "`$gSource'");
     }
+    dprint(3, "Found " . keys(%patchdata) . " ROM-patched components");
 
-    splice(@$obydata, $offset, 0, @torofs1) if @torofs1;
+    splice(@$obydata, $rofs1ofs, 0, @torofs1) if @torofs1;
 
     plugin_end();
 }
 
+sub obyparse_findincfiles()
+{
+    my ($drive, $indent, $prev, $tmpoby, %files) =
+        (Cwd::cwd() =~ /^([a-z]:)/i ? $1 : "", -2, "", "$gWorkdir/tmp1.oby", ());
+
+    dprint(3, "Finding include hierarchy from `$tmpoby'");
+    open(FILE, $tmpoby) or dprint(-3, "$gPluginname can't open `$tmpoby'"), return;
+
+    while (my $line = <FILE>) {
+        next if ($line !~ /^#\s+\d+\s+"(.+?)"(?:\s+(\d))?$/);
+        my ($file, $flag) = ($1, defined($2) ? $2 : 0);
+        next if ($file =~ /^<.*>$/);
+        $indent -= 2, $prev = $file, next if ($flag == 2);
+        next if (!$flag && $file eq $prev || $flag > 1);
+        $indent += 2 if $flag;
+        ($prev = $file) =~ /^(.*[\/\\])?(.+?)$/;
+        (my $dir, $file) = ("", $2);
+        $dir = abspath(defined($1) ? $1 : ".");
+        dprint(2, ("." x $indent) . "`$prev' !!!"), next if ($dir eq "");
+        $dir =~ s/^$drive|\/$//gi;
+        $files{lc($file = "$dir/$file")} = 1;
+        dprint(2, ("." x $indent) . "`$file'");
+    }
+    close(FILE);
+    dprint(3, "Found " . keys(%files) . " different include files");
+}
+
+sub obyparse_findspifiles()
+{
+    my ($spicnt, $tmpoby) = (0, "$gWorkdir/tmp5.oby");
+
+    dprint(3, "Finding SPI input files from `$tmpoby'");
+    open(FILE, $tmpoby) or dprint(-3, "$gPluginname can't open `$tmpoby'"), return;
+
+    while (my $line = <FILE>) {
+        next if (parse_obyline($line) != 2) || ($gKeyword !~ /^spidata/i);
+        $spicnt++;
+        dprint(2, "`$gSource'" . ($gKeyword =~ /^spidata$/i ? "" : " ($gKeyword)"));
+    }
+    close(FILE);
+    dprint(3, "Found $spicnt SPI input files");
+}
 
 sub obyparse_readconffile($$$$$)
 {
     my ($basedir, $file, $type, $files, $indent) = @_;
-    $file = $basedir . $file;
+    $file = "$basedir$file";
     my $filecnt = 0;
 
-    dprint(3, "Reading $type files") if $type;
-    dprint(3, ("." x $indent) . "`$file'");
+    dprint(3, "Reading $type files from $file") if $type;
+    dprint(2, ("." x $indent) . "`$file'");
 
-    open(FILE, $file) or die("ERROR: Can't open `$file'\n");
+    open(FILE, $file) or dprint(3, "Error: $gPluginname can't open $file", 1), die("\n");
+    my @files = <FILE>;
+    close(FILE);
 
-    foreach my $line (<FILE>) {
-        if ($line =~ /^\s*#include\s+(.+?)\s*$/i) {
+    foreach (@files) {
+        if (/^\s*#include\s+(.+?)\s*$/i) {
             $filecnt += obyparse_readconffile($basedir, $1, "", $files, $indent + 2);
             next;
         }
-        next if ($line =~ /^\s*$/) || ($line =~ /^\s*(?:#|\/\/|REM\s)/i);
+        next if (/^\s*$/) || (/^\s*(?:#|\/\/|REM\s)/i);
         $filecnt++;
-        (my $fname = $line) =~ s/^\s+|\s+$//g;
-        $fname =~ s/(.)/{'*' => '.*', '?' => '.', '[' => '[', ']' => ']'}->{$1} || "\Q$1\E"/ge;
+        (my $fname = $_) =~ s/^\s+|\s+$//g;
+        $fname =~ s/(.)/{"*" => ".*", "?" => "."}->{$1} || "\Q$1\E"/eg;
         $$files .= ($$files eq "" ? "" : "|") . $fname;
     }
-    close(FILE);
     return($filecnt);
 }