| #!/usr/bin/perl -w |
| |
| # Copyright (C) 2008 Apple Inc. All Rights Reserved. |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| use strict; |
| use File::Basename; |
| |
| sub printDependencyTree($); |
| |
| my $basename = basename($0); |
| @ARGV or die "Usage: $basename sln1 [sln2 sln3...]"; |
| |
| foreach my $sln (@ARGV) { |
| printDependencyTree($sln); |
| } |
| |
| exit; |
| |
| sub printDependencyTree($) |
| { |
| my ($sln) = @_; |
| |
| unless (-f $sln) { |
| warn "Warning: Can't find $sln; skipping\n"; |
| return; |
| } |
| |
| unless (open SLN, "<", $sln) { |
| warn "Warning: Can't open $sln; skipping\n"; |
| return; |
| } |
| |
| my %projectsByUUID = (); |
| my $currentProject; |
| |
| my $state = "initial"; |
| foreach my $line (<SLN>) { |
| if ($state eq "initial") { |
| if ($line =~ /^Project\([^\)]+\) = "([^"]+)", "[^"]+", "([^"]+)"\r?$/) { |
| my $name = $1; |
| my $uuid = $2; |
| if (exists $projectsByUUID{$uuid}) { |
| warn "Warning: Project $name appears more than once in $sln; using first definition\n"; |
| next; |
| } |
| $currentProject = { |
| name => $name, |
| uuid => $uuid, |
| dependencies => {}, |
| }; |
| $projectsByUUID{$uuid} = $currentProject; |
| |
| $state = "inProject"; |
| } |
| |
| next; |
| } |
| |
| if ($state eq "inProject") { |
| defined($currentProject) or die; |
| |
| if ($line =~ /^\s*ProjectSection\(ProjectDependencies\) = postProject\r?$/) { |
| $state = "inDependencies"; |
| } elsif ($line =~ /^EndProject\r?$/) { |
| $currentProject = undef; |
| $state = "initial"; |
| } |
| |
| next; |
| } |
| |
| if ($state eq "inDependencies") { |
| defined($currentProject) or die; |
| |
| if ($line =~ /^\s*({[^}]+}) = ({[^}]+})\r?$/) { |
| my $uuid1 = $1; |
| my $uuid2 = $2; |
| if (exists $currentProject->{dependencies}->{$uuid1}) { |
| warn "Warning: UUID $uuid1 listed more than once as dependency of project ", $currentProject->{name}, "\n"; |
| next; |
| } |
| |
| $uuid1 eq $uuid2 or warn "Warning: UUIDs in depedency section of project ", $currentProject->{name}, " don't match: $uuid1 $uuid2; using first UUID\n"; |
| |
| $currentProject->{dependencies}->{$uuid1} = 1; |
| } elsif ($line =~ /^\s*EndProjectSection\r?$/) { |
| $state = "inProject"; |
| } |
| |
| next; |
| } |
| } |
| |
| close SLN or warn "Warning: Can't close $sln\n"; |
| |
| my %projectsNotDependedUpon = %projectsByUUID; |
| CANDIDATE: foreach my $candidateUUID (keys %projectsByUUID) { |
| foreach my $projectUUID (keys %projectsByUUID) { |
| next if $candidateUUID eq $projectUUID; |
| foreach my $dependencyUUID (keys %{$projectsByUUID{$projectUUID}->{dependencies}}) { |
| if ($candidateUUID eq $dependencyUUID) { |
| delete $projectsNotDependedUpon{$candidateUUID}; |
| next CANDIDATE; |
| } |
| } |
| } |
| } |
| |
| foreach my $project (values %projectsNotDependedUpon) { |
| printProjectAndDependencies($project, 0, \%projectsByUUID); |
| } |
| } |
| |
| sub printProjectAndDependencies |
| { |
| my ($project, $indentLevel, $projectsByUUID) = @_; |
| |
| print " " x $indentLevel, $project->{name}, "\n"; |
| foreach my $dependencyUUID (keys %{$project->{dependencies}}) { |
| printProjectAndDependencies($projectsByUUID->{$dependencyUUID}, $indentLevel + 1, $projectsByUUID); |
| } |
| } |