Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

416 lines
11 KiB

  1. package WhatsNew;
  2. use Getp;
  3. ($Alias, $BinRoot, $BinPattern, $SymPattern, $PriSymPattern, $CommentPattern, $AliasList, $BinList, $HELP, $Powerless, $FullAlias) = ();
  4. my $AliasFileFormat =
  5. "<Alias>,\\s+<BinRoot>,\\s+<BinPattern>,\\s+<SymPattern>,\\s+<PriSymPattern>,\\s+<CommentPattern>";
  6. my $BinFileFormat =
  7. "<Bin>,\\s+<Symbols>,\\s+<PriSymbols>,\\s+<FileCounter>,\\s+<LatestTime>,\\s+<TotalTime>,\\s+<Revision>,\\s+<BinRoot>,\\s+<Comment>";
  8. my (@Aliases, @AliasItems, @BinItems) = ();
  9. my (%ArgHash, %AliasHash, %BinHash) = ();
  10. my (@Pieces, @NameSpace, %NameValue) = ();
  11. my ($tBinRoot, $tBinPattern, $tSymPattern, $tPriSymPattern, $tComment);
  12. (@AliasItemNames) = $AliasFileFormat =~ /\<(\w+)\>/g;
  13. sub Main {
  14. my (@Bins, $comment);
  15. open(LOG, ">test.log");
  16. &LoadAliasHash($AliasList);
  17. &LoadBinHash($BinList);
  18. @Aliases = &StoreAlias($Alias);
  19. for $Alias (@Aliases) {
  20. @Bins = &FindBins($Alias);
  21. for $tBin (@Bins) {
  22. $_ = &QuickCheck($tBin);
  23. if (/NETWORK/ || /SKIP/) {
  24. next;
  25. }
  26. if (/DELETE/) {
  27. # system("symstore del /i id /s $tBin");
  28. }
  29. if (/CHECK/) {
  30. $comment = ("$BinHash{$tBin}->{Comment}" ne "")?"/c $BinHash{$tBin}->{Comment}":"";
  31. $IndexFile = $tBin;
  32. $IndexFile =~ s/\_/\___/g; # _=>___
  33. $IndexFile =~ s/\\/\_/g;
  34. print $_ . "\n";
  35. print "Check Bin - $tBin\n";
  36. next if (defined $Powerless);
  37. $BinHash{$tBin}->{Revision}++;
  38. print("Symstore add /a /p /r /f $tBin /g $BinHash{$tBin}->{BinRoot} /x index\\${IndexFile}.${BinHash{$tBin}->{Revision}}.bin $comment");
  39. system("symstore add /a /p /r /f $tBin /g $BinHash{$tBin}->{BinRoot} /x index\\${IndexFile}.${BinHash{$tBin}->{Revision}}.bin $comment");
  40. 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});
  41. 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});
  42. }
  43. &UpdateTotal($tBin);
  44. }
  45. &SaveBinHash($BinList) if (defined $Powerless);
  46. &SaveAliasHash($AliasList) if (defined $Powerless);
  47. }
  48. close(LOG);
  49. }
  50. sub FindBins {
  51. ($tAlias) = @_;
  52. my (@Bins, $tBin);
  53. my ($BinRoot, $BinPattern, $SymPattern, $PriSymPattern, $CommentPattern) =
  54. map({$AliasHash{$tAlias}->{$_}} @AliasItemNames[1..$#AliasItemNames]);
  55. $BinPattern = $BinRoot . "\\" . $BinPattern;
  56. $SymPattern = $BinRoot . "\\" . $SymPattern if (defined $SymPattern);
  57. $PriSymPattern = $BinRoot . "\\" . $PriSymPattern if (defined $PriSymPattern);
  58. @Bins = &FindPattern($BinRoot, $BinPattern, $SymPattern, $PriSymPattern, $CommentPattern);
  59. return @Bins;
  60. }
  61. sub FindPattern {
  62. ($tBinRoot, $tBinPattern, $tSymPattern, $tPriSymPattern, $tComment) = @_;
  63. my (@Names, $namepattern);
  64. my (%Checked, @RetResult)=();
  65. my ($i, $path)=(0);
  66. # @NameSpace = [$Name, $pattern];
  67. (@Names) = $tBinPattern=~/\#([^\#]+)\#/g;
  68. for $namepattern (@Names) {
  69. $namepattern =~ /([^\:]+)(?:\:(.+))?/;
  70. my ($name, $pattern) = ($1, $2);
  71. $pattern = ".+" if (!defined $pattern);
  72. $NameSpace[$i]=[$name, $pattern];
  73. $NameValue{$name}="";
  74. $i++;
  75. }
  76. @Pieces = split(/\#[^\#]+\#/, $tBinPattern); # No support for recursive parenthesis
  77. return &RecDir(1, $Pieces[0]);
  78. }
  79. sub RecDir {
  80. my ($i, $path) = @_;
  81. my (@ret, $mypath, @paths);
  82. if ($i == (scalar @Pieces)) {
  83. if (-d $path) {
  84. $BinHash{$path}->{Symbols} = &Evaluate($tSymPattern, \%NameValue);
  85. $BinHash{$path}->{PriSymbols} = &Evaluate($tPriSymPattern, \%NameValue);
  86. $BinHash{$path}->{FileCounter} = 0 if (!defined $BinHash{$path}->{FileCounter});
  87. $BinHash{$path}->{LatestTime} = 0 if (!defined $BinHash{$path}->{LatestTime});
  88. $BinHash{$path}->{TotalTime} = 0 if (!defined $BinHash{$path}->{TotalTime});
  89. $BinHash{$path}->{Revision} = 0 if (!defined $BinHash{$path}->{Revision});
  90. $BinHash{$path}->{BinRoot} = $tBinRoot;
  91. $BinHash{$path}->{Comment} = &Evaluate($tComment, \%NameValue);
  92. return $path;
  93. } else {
  94. return;
  95. }
  96. } else {
  97. opendir(DIR, $path);
  98. @paths = map({/\w+/?$path . $_:()} readdir(DIR));
  99. closedir(DIR);
  100. for $mypath (@paths) {
  101. if ((-d $mypath) &&
  102. (substr($mypath,length($path)) =~ /^$NameSpace[$i-1][1]$/i)) {
  103. $NameValue{$NameSpace[$i-1][0]} = substr($mypath, length($path));
  104. push @ret, &RecDir($i + 1, $mypath . $Pieces[$i]);
  105. }
  106. }
  107. return @ret;
  108. }
  109. }
  110. sub Evaluate {
  111. my ($path, $hNameValue) = @_;
  112. $path=~s/\#([^\#]+)(?:\:[^\#]+)?\#/$hNameValue->{$1}/ge;
  113. return $path;
  114. }
  115. sub QuickCheck {
  116. my ($Bin) = @_;
  117. my $hInfo = $BinHash{$Bin};
  118. my ($myTotalTime, $myFCtr, $myfile, $myTime)=(0,0,"");
  119. my ($yy, $mm, $dd, $hh, $mn, $ss);
  120. open(F, "dir /s /b /a-d /o-d $Bin|") or return "NETWORK";
  121. $myfile = <F>;
  122. chomp $myfile;
  123. $myTotalTime = (lstat($myfile))[9];
  124. $myFCtr=1;
  125. ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($mytotalTime))[5,4,3,2,1,0];
  126. printf LOG ("C: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $myfile, $yy+1900, $mm+1, $dd, $hh, $mn, $ss);
  127. return "DELETE" if ($myfile !~ /\S/);
  128. return "CHECK 1 - $myTotalTime $hInfo->{LatestTime}" if ($myTotalTime != $hInfo->{LatestTime});
  129. while (<F>) {
  130. chomp;
  131. $myFCtr++;
  132. $myTotalTime += $myTime = (lstat($_))[9];
  133. ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($myTime))[5,4,3,2,1,0];
  134. printf LOG ("C: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $_, $yy+1900, $mm+1, $dd, $hh, $mn, $ss);
  135. if ($myTotalTime > $hInfo->{TotalTime}) {
  136. return "CHECK 2 - $myTotalTime, $hInfo->{TotalTime}";
  137. }
  138. }
  139. close(F);
  140. (($hInfo->{TotalTime}==$myTotalTime) && ($hInfo->{FileCounter}==$myFCtr))?"SKIP":"CHECK 3 - $hInfo->{TotalTime}, $myTotalTime, $hInfo->{FileCounter}, $myFCtr";
  141. }
  142. sub StoreAlias {
  143. my ($tAlias)=@_;
  144. return keys %AliasHash if (defined $FullAlias);
  145. if ($tAlias=~/\,/) {
  146. # Store the new alias into %TargetAlias
  147. $AliasHash{$tAlias} = {
  148. BinRoot => $BinRoot,
  149. BinPattern => $BinPattern,
  150. SymPattern => $SymPattern,
  151. PriSymPattern => $PriSymPattern,
  152. CommentPattern => $CommentPattern
  153. } if (defined $BinRoot);
  154. return $tAlias;
  155. } else {
  156. return split(/\,/, $tAlias);
  157. }
  158. }
  159. sub UpdateTotal {
  160. my ($tBin)=@_;
  161. my ($tFileCounter, $tLatestTime, $tTotalTime) = (0, 0, 0);
  162. my ($myfile, $myTime);
  163. my ($yy, $mm, $dd, $hh, $mn, $ss);
  164. open(F, "dir /s /b /a-d /o-d $tBin|") or return "NETWORK";
  165. $myfile = <F>;
  166. chomp $myfile;
  167. $tTotalTime = $tLatestTime = (lstat($myfile))[9];
  168. $tFileCounter++;
  169. ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($tTotalTime))[5,4,3,2,1,0];
  170. printf LOG ("U: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $myfile, $yy+1900, $mm+1, $dd, $hh, $mn, $ss);
  171. while(<F>) {
  172. chomp;
  173. $tTotalTime += $myTime = (lstat($_))[9];
  174. $tFileCounter++;
  175. ($yy, $mm, $dd, $hh, $mn, $ss) = (localtime($myTime))[5,4,3,2,1,0];
  176. printf LOG ("U: %s, %04d/%02d/%02d %02d:%02d:%02d\n", $_, $yy+1900, $mm+1, $dd, $hh, $mn, $ss);
  177. }
  178. $BinHash{$tBin}->{FileCounter} = $tFileCounter;
  179. $BinHash{$tBin}->{LatestTime} = $tLatestTime;
  180. $BinHash{$tBin}->{TotalTime} = $tTotalTime;
  181. close(F);
  182. }
  183. sub LoadBinHash {
  184. my ($FileName) = @_;
  185. &LoadFileToHash($FileName, \%BinHash, $BinFileFormat);
  186. }
  187. sub SaveBinHash {
  188. my ($FileName) = @_;
  189. &SaveHashToFile($FileName, \%BinHash, $BinFileFormat);
  190. }
  191. sub LoadAliasHash {
  192. my ($FileName) = @_;
  193. &LoadFileToHash($FileName, \%AliasHash, $AliasFileFormat);
  194. }
  195. sub SaveAliasHash {
  196. my ($FileName) = @_;
  197. &SaveHashToFile($FileName, \%AliasHash, $AliasFileFormat);
  198. }
  199. sub LoadFileToHash {
  200. my ($FileName, $refHash, $HashFormat) = @_;
  201. local $_;
  202. my ($Key1, $Pattern, @Keys2, @Values2)=();
  203. $KeyNames = $HashFormat;
  204. (@Keys2) = $HashFormat =~ /\<(\w+)\>/g;
  205. shift @Keys2; # Remove the first level hash key name
  206. $Pattern = $HashFormat;
  207. $Pattern =~ s/\<\w+\>/\(\\S+\)/g;
  208. open(F, $FileName);
  209. while(<F>) {
  210. chomp;
  211. (@Values)=/$Pattern/;
  212. $Key1 = shift @Values;
  213. map({ my ($key2, $value) = ($_, shift @Values);
  214. $refHash->{$Key1}->{$key2} = ($value eq "-")?undef:$value;
  215. } @Keys2);
  216. }
  217. close(F);
  218. }
  219. sub SaveHashToFile {
  220. my ($FileName, $refHash, $HashFormat) = @_;
  221. local $_;
  222. my (%formlength, $myFormat, $ctr, $ctr_old);
  223. my ($Key1, $Pattern, @Keys2, @Values2)=();
  224. $KeyNames = $HashFormat;
  225. (@Keys2) = $HashFormat =~ /\<(\w+)\>/g;
  226. map({$formlength{$_}=length($_)} @Keys2);
  227. for $Key1 (keys %$refHash) {
  228. next if($Key1 eq '');
  229. $formlength{$Keys2[0]} = length($Key1)
  230. if($formlength{$Keys2[0]} < length($Key1));
  231. for $Key2 (keys %{$refHash->{$Key1}}) {
  232. $formlength{$Key2} = length($refHash->{$Key1}->{$Key2})
  233. if($formlength{$Key2} < length($refHash->{$Key1}->{$Key2}));
  234. }
  235. }
  236. $Format = $HashFormat;
  237. $Format =~ s/\<(\w+)\>/\%s/g;
  238. open(F, ">" . $FileName);
  239. for $Key1 (sort keys %$refHash) {
  240. $refHash->{$Key1}->{$Keys2[0]}=$Key1;
  241. @Values2 = map({(defined $refHash->{$Key1}->{$_})?$refHash->{$Key1}->{$_}:"-"} @Keys2);
  242. $myFormat = $Format;
  243. $ctr_old = $spaces = 0;
  244. while ($myFormat=~/\\s\+/) {
  245. my($pre, $match, $post) = ($`, $&, $');
  246. $ctr = 0;
  247. map({$ctr++;} ($pre=~/\%/g));
  248. splice(@Values2, $ctr, 0, " ");
  249. $myFormat = $pre .
  250. "\%" .
  251. sprintf("%d", &AdjustSpace( \%formlength, $refHash, $Key1, \@Keys2, $ctr_old, $ctr - $spaces)+1 ) .
  252. "s" .
  253. $post;
  254. $ctr_old=$ctr - $spaces;
  255. $spaces++;
  256. }
  257. printf F ($myFormat, @Values2);
  258. print F "\n";
  259. }
  260. close(F);
  261. }
  262. sub AdjustSpace {
  263. my ($formlengthptr, $refHash, $Key1, $refKeys2, $i, $j) = @_;
  264. my $sum=0;
  265. map({
  266. if (defined $refHash->{$Key1}->{$_}) {
  267. $sum+=$formlengthptr->{$_} - length($refHash->{$Key1}->{$_});
  268. } else {
  269. $sum+=$formlengthptr->{$_} - 1;
  270. }
  271. } @$refKeys2[$i..$j-1]);
  272. return $sum;
  273. }
  274. sub ParseArgument {
  275. my @unsolve = Getp::GetParams(
  276. -o => "a: f r: b: s: p: c: l: i: z " .
  277. "alias>a root>r bin>b sym>s pri>p cmt>c alist>l blist>b",
  278. -h => \%ArgHash,
  279. -p => "Alias FullAlias BinRoot BinPattern SymPattern PriSymPattern CommentPattern AliasList BinList Powerless",
  280. @ARGV
  281. );
  282. print "Error: Unsolve argument: $Getp::_UNSOLVE\n" if defined ($Getp::_UNSOLVE);
  283. if ($Getp::HELP eq 1) {
  284. &Usage;
  285. exit(1);
  286. }
  287. if (!defined $AliasList) {
  288. $AliasList = "AliasList.txt";
  289. }
  290. if (!defined $BinList) {
  291. $BinList = "BinList.txt";
  292. }
  293. if ((!defined $Alias) && (!defined $FullAlias)) {
  294. &Usage;
  295. print "Please defined either -a:<alias> or -f\n";
  296. }
  297. }
  298. sub Usage {
  299. print <<USAGE;
  300. $0 - Find What is new in the tree
  301. ------------------------------------------------------
  302. Syntax:
  303. $0 -a[lias]:<alias>
  304. [-r[oot]:<root> -b[in]:<bin> -s[ym]:<sym> -p[ri]:<pri> -c[mt]:<cmt>]
  305. [-<l|alist>:<alist>] [-<i|blist>:<blist>] [-z]
  306. Parameters:
  307. alias - The project name or any alias. Such as SP2
  308. root - The root path. Such as \\\\winseqfe\\release\\w2k\\sp2
  309. bin - The binary path.
  310. Such as \#buildnum:[\\d\^|\\.]+\#\\\#lang\#\\x86\\\#frechk:fre\^|chk\#\\stf\\binaries
  311. sym - The symbols path. Such as \#buildnum\#\\\#lang\#\\x86\\\#frechk\#\\sym
  312. pri - The private symbols. Such as \#buildnum\#\\\#lang\#\\x86\\\#frechk\#\\sym
  313. cmt - The comment. Such as, Windows SP2 build \#buildnum\#
  314. alist - The filename of the AliasList. Such as aliaslist.txt (default)
  315. blist - The filename of the BinList. Such as binlist.txt. (default)
  316. Options:
  317. -z - powerless
  318. USAGE
  319. return;
  320. }
  321. if (eval("\$0=~/" . __PACKAGE__ . "\\.pl\$/i")) {
  322. &ParseArgument;
  323. &Main;
  324. }
  325. 1;