package WhatsNew; use Getp; ($Alias, $BinRoot, $BinPattern, $SymPattern, $PriSymPattern, $CommentPattern, $AliasList, $BinList, $HELP, $Powerless, $FullAlias) = (); my $AliasFileFormat = ",\\s+,\\s+,\\s+,\\s+,\\s+"; my $BinFileFormat = ",\\s+,\\s+,\\s+,\\s+,\\s+,\\s+,\\s+,\\s+"; my (@Aliases, @AliasItems, @BinItems) = (); my (%ArgHash, %AliasHash, %BinHash) = (); my (@Pieces, @NameSpace, %NameValue) = (); my ($tBinRoot, $tBinPattern, $tSymPattern, $tPriSymPattern, $tComment); (@AliasItemNames) = $AliasFileFormat =~ /\<(\w+)\>/g; sub Main { my (@Bins, $comment); open(LOG, ">test.log"); &LoadAliasHash($AliasList); &LoadBinHash($BinList); @Aliases = &StoreAlias($Alias); for $Alias (@Aliases) { @Bins = &FindBins($Alias); for $tBin (@Bins) { $_ = &QuickCheck($tBin); if (/NETWORK/ || /SKIP/) { next; } if (/DELETE/) { # system("symstore del /i id /s $tBin"); } if (/CHECK/) { $comment = ("$BinHash{$tBin}->{Comment}" ne "")?"/c $BinHash{$tBin}->{Comment}":""; $IndexFile = $tBin; $IndexFile =~ s/\_/\___/g; # _=>___ $IndexFile =~ s/\\/\_/g; print $_ . "\n"; print "Check Bin - $tBin\n"; next if (defined $Powerless); $BinHash{$tBin}->{Revision}++; print("Symstore add /a /p /r /f $tBin /g $BinHash{$tBin}->{BinRoot} /x index\\${IndexFile}.${BinHash{$tBin}->{Revision}}.bin $comment"); system("symstore add /a /p /r /f $tBin /g $BinHash{$tBin}->{BinRoot} /x index\\${IndexFile}.${BinHash{$tBin}->{Revision}}.bin $comment"); system("symstore add /a /p /r /f $BinHash{$tBin}->{Symbols} /g $BinHash{$tBin}->{BinRoot} /x index\\${IndexFile}.${BinHash{$tBin}->{Revision}}.sym $comment") if (defined $BinHash{$tBin}->{Symbols}); system("symstore add /a /p /r /f $BinHash{$tBin}->{PriSymbols} /g $BinHash{$tBin}->{BinRoot} /x index\\${IndexFile}.${BinHash{$tBin}->{Revision}}.pri $comment") if (defined $BinHash{$tBin}->{PriSymbols}); } &UpdateTotal($tBin); } &SaveBinHash($BinList) if (defined $Powerless); &SaveAliasHash($AliasList) if (defined $Powerless); } close(LOG); } sub FindBins { ($tAlias) = @_; my (@Bins, $tBin); my ($BinRoot, $BinPattern, $SymPattern, $PriSymPattern, $CommentPattern) = map({$AliasHash{$tAlias}->{$_}} @AliasItemNames[1..$#AliasItemNames]); $BinPattern = $BinRoot . "\\" . $BinPattern; $SymPattern = $BinRoot . "\\" . $SymPattern if (defined $SymPattern); $PriSymPattern = $BinRoot . "\\" . $PriSymPattern if (defined $PriSymPattern); @Bins = &FindPattern($BinRoot, $BinPattern, $SymPattern, $PriSymPattern, $CommentPattern); return @Bins; } sub FindPattern { ($tBinRoot, $tBinPattern, $tSymPattern, $tPriSymPattern, $tComment) = @_; my (@Names, $namepattern); my (%Checked, @RetResult)=(); my ($i, $path)=(0); # @NameSpace = [$Name, $pattern]; (@Names) = $tBinPattern=~/\#([^\#]+)\#/g; for $namepattern (@Names) { $namepattern =~ /([^\:]+)(?:\:(.+))?/; my ($name, $pattern) = ($1, $2); $pattern = ".+" if (!defined $pattern); $NameSpace[$i]=[$name, $pattern]; $NameValue{$name}=""; $i++; } @Pieces = split(/\#[^\#]+\#/, $tBinPattern); # No support for recursive parenthesis return &RecDir(1, $Pieces[0]); } sub RecDir { my ($i, $path) = @_; my (@ret, $mypath, @paths); if ($i == (scalar @Pieces)) { if (-d $path) { $BinHash{$path}->{Symbols} = &Evaluate($tSymPattern, \%NameValue); $BinHash{$path}->{PriSymbols} = &Evaluate($tPriSymPattern, \%NameValue); $BinHash{$path}->{FileCounter} = 0 if (!defined $BinHash{$path}->{FileCounter}); $BinHash{$path}->{LatestTime} = 0 if (!defined $BinHash{$path}->{LatestTime}); $BinHash{$path}->{TotalTime} = 0 if (!defined $BinHash{$path}->{TotalTime}); $BinHash{$path}->{Revision} = 0 if (!defined $BinHash{$path}->{Revision}); $BinHash{$path}->{BinRoot} = $tBinRoot; $BinHash{$path}->{Comment} = &Evaluate($tComment, \%NameValue); return $path; } else { return; } } else { opendir(DIR, $path); @paths = map({/\w+/?$path . $_:()} readdir(DIR)); closedir(DIR); for $mypath (@paths) { if ((-d $mypath) && (substr($mypath,length($path)) =~ /^$NameSpace[$i-1][1]$/i)) { $NameValue{$NameSpace[$i-1][0]} = substr($mypath, length($path)); push @ret, &RecDir($i + 1, $mypath . $Pieces[$i]); } } return @ret; } } sub Evaluate { my ($path, $hNameValue) = @_; $path=~s/\#([^\#]+)(?:\:[^\#]+)?\#/$hNameValue->{$1}/ge; return $path; } sub QuickCheck { my ($Bin) = @_; my $hInfo = $BinHash{$Bin}; my ($myTotalTime, $myFCtr, $myfile, $myTime)=(0,0,""); my ($yy, $mm, $dd, $hh, $mn, $ss); open(F, "dir /s /b /a-d /o-d $Bin|") or return "NETWORK"; $myfile = ; chomp $myfile; $myTotalTime = (lstat($myfile))[9]; $myFCtr=1; ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($mytotalTime))[5,4,3,2,1,0]; printf LOG ("C: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $myfile, $yy+1900, $mm+1, $dd, $hh, $mn, $ss); return "DELETE" if ($myfile !~ /\S/); return "CHECK 1 - $myTotalTime $hInfo->{LatestTime}" if ($myTotalTime != $hInfo->{LatestTime}); while () { chomp; $myFCtr++; $myTotalTime += $myTime = (lstat($_))[9]; ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($myTime))[5,4,3,2,1,0]; printf LOG ("C: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $_, $yy+1900, $mm+1, $dd, $hh, $mn, $ss); if ($myTotalTime > $hInfo->{TotalTime}) { return "CHECK 2 - $myTotalTime, $hInfo->{TotalTime}"; } } close(F); (($hInfo->{TotalTime}==$myTotalTime) && ($hInfo->{FileCounter}==$myFCtr))?"SKIP":"CHECK 3 - $hInfo->{TotalTime}, $myTotalTime, $hInfo->{FileCounter}, $myFCtr"; } sub StoreAlias { my ($tAlias)=@_; return keys %AliasHash if (defined $FullAlias); if ($tAlias=~/\,/) { # Store the new alias into %TargetAlias $AliasHash{$tAlias} = { BinRoot => $BinRoot, BinPattern => $BinPattern, SymPattern => $SymPattern, PriSymPattern => $PriSymPattern, CommentPattern => $CommentPattern } if (defined $BinRoot); return $tAlias; } else { return split(/\,/, $tAlias); } } sub UpdateTotal { my ($tBin)=@_; my ($tFileCounter, $tLatestTime, $tTotalTime) = (0, 0, 0); my ($myfile, $myTime); my ($yy, $mm, $dd, $hh, $mn, $ss); open(F, "dir /s /b /a-d /o-d $tBin|") or return "NETWORK"; $myfile = ; chomp $myfile; $tTotalTime = $tLatestTime = (lstat($myfile))[9]; $tFileCounter++; ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($tTotalTime))[5,4,3,2,1,0]; printf LOG ("U: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $myfile, $yy+1900, $mm+1, $dd, $hh, $mn, $ss); while() { chomp; $tTotalTime += $myTime = (lstat($_))[9]; $tFileCounter++; ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($myTime))[5,4,3,2,1,0]; printf LOG ("U: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $_, $yy+1900, $mm+1, $dd, $hh, $mn, $ss); } $BinHash{$tBin}->{FileCounter} = $tFileCounter; $BinHash{$tBin}->{LatestTime} = $tLatestTime; $BinHash{$tBin}->{TotalTime} = $tTotalTime; close(F); } sub LoadBinHash { my ($FileName) = @_; &LoadFileToHash($FileName, \%BinHash, $BinFileFormat); } sub SaveBinHash { my ($FileName) = @_; &SaveHashToFile($FileName, \%BinHash, $BinFileFormat); } sub LoadAliasHash { my ($FileName) = @_; &LoadFileToHash($FileName, \%AliasHash, $AliasFileFormat); } sub SaveAliasHash { my ($FileName) = @_; &SaveHashToFile($FileName, \%AliasHash, $AliasFileFormat); } sub LoadFileToHash { my ($FileName, $refHash, $HashFormat) = @_; local $_; my ($Key1, $Pattern, @Keys2, @Values2)=(); $KeyNames = $HashFormat; (@Keys2) = $HashFormat =~ /\<(\w+)\>/g; shift @Keys2; # Remove the first level hash key name $Pattern = $HashFormat; $Pattern =~ s/\<\w+\>/\(\\S+\)/g; open(F, $FileName); while() { chomp; (@Values)=/$Pattern/; $Key1 = shift @Values; map({ my ($key2, $value) = ($_, shift @Values); $refHash->{$Key1}->{$key2} = ($value eq "-")?undef:$value; } @Keys2); } close(F); } sub SaveHashToFile { my ($FileName, $refHash, $HashFormat) = @_; local $_; my (%formlength, $myFormat, $ctr, $ctr_old); my ($Key1, $Pattern, @Keys2, @Values2)=(); $KeyNames = $HashFormat; (@Keys2) = $HashFormat =~ /\<(\w+)\>/g; map({$formlength{$_}=length($_)} @Keys2); for $Key1 (keys %$refHash) { next if($Key1 eq ''); $formlength{$Keys2[0]} = length($Key1) if($formlength{$Keys2[0]} < length($Key1)); for $Key2 (keys %{$refHash->{$Key1}}) { $formlength{$Key2} = length($refHash->{$Key1}->{$Key2}) if($formlength{$Key2} < length($refHash->{$Key1}->{$Key2})); } } $Format = $HashFormat; $Format =~ s/\<(\w+)\>/\%s/g; open(F, ">" . $FileName); for $Key1 (sort keys %$refHash) { $refHash->{$Key1}->{$Keys2[0]}=$Key1; @Values2 = map({(defined $refHash->{$Key1}->{$_})?$refHash->{$Key1}->{$_}:"-"} @Keys2); $myFormat = $Format; $ctr_old = $spaces = 0; while ($myFormat=~/\\s\+/) { my($pre, $match, $post) = ($`, $&, $'); $ctr = 0; map({$ctr++;} ($pre=~/\%/g)); splice(@Values2, $ctr, 0, " "); $myFormat = $pre . "\%" . sprintf("%d", &AdjustSpace( \%formlength, $refHash, $Key1, \@Keys2, $ctr_old, $ctr - $spaces)+1 ) . "s" . $post; $ctr_old=$ctr - $spaces; $spaces++; } printf F ($myFormat, @Values2); print F "\n"; } close(F); } sub AdjustSpace { my ($formlengthptr, $refHash, $Key1, $refKeys2, $i, $j) = @_; my $sum=0; map({ if (defined $refHash->{$Key1}->{$_}) { $sum+=$formlengthptr->{$_} - length($refHash->{$Key1}->{$_}); } else { $sum+=$formlengthptr->{$_} - 1; } } @$refKeys2[$i..$j-1]); return $sum; } sub ParseArgument { my @unsolve = Getp::GetParams( -o => "a: f r: b: s: p: c: l: i: z " . "alias>a root>r bin>b sym>s pri>p cmt>c alist>l blist>b", -h => \%ArgHash, -p => "Alias FullAlias BinRoot BinPattern SymPattern PriSymPattern CommentPattern AliasList BinList Powerless", @ARGV ); print "Error: Unsolve argument: $Getp::_UNSOLVE\n" if defined ($Getp::_UNSOLVE); if ($Getp::HELP eq 1) { &Usage; exit(1); } if (!defined $AliasList) { $AliasList = "AliasList.txt"; } if (!defined $BinList) { $BinList = "BinList.txt"; } if ((!defined $Alias) && (!defined $FullAlias)) { &Usage; print "Please defined either -a: or -f\n"; } } sub Usage { print < [-r[oot]: -b[in]: -s[ym]: -p[ri]: -c[mt]:] [-:] [-:] [-z] Parameters: alias - The project name or any alias. Such as SP2 root - The root path. Such as \\\\winseqfe\\release\\w2k\\sp2 bin - The binary path. Such as \#buildnum:[\\d\^|\\.]+\#\\\#lang\#\\x86\\\#frechk:fre\^|chk\#\\stf\\binaries sym - The symbols path. Such as \#buildnum\#\\\#lang\#\\x86\\\#frechk\#\\sym pri - The private symbols. Such as \#buildnum\#\\\#lang\#\\x86\\\#frechk\#\\sym cmt - The comment. Such as, Windows SP2 build \#buildnum\# alist - The filename of the AliasList. Such as aliaslist.txt (default) blist - The filename of the BinList. Such as binlist.txt. (default) Options: -z - powerless USAGE return; } if (eval("\$0=~/" . __PACKAGE__ . "\\.pl\$/i")) { &ParseArgument; &Main; } 1;