diff -r 22486c9c7b15 -r 378360dbbdba sbsv1/abld/e32util/checksource.pm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sbsv1/abld/e32util/checksource.pm Wed Jun 30 11:35:58 2010 +0800 @@ -0,0 +1,471 @@ +# Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies). +# All rights reserved. +# This component and the accompanying materials are made available +# under the terms of "Eclipse Public License v1.0" +# which accompanies this distribution, and is available +# at the URL "http://www.eclipse.org/legal/epl-v10.html". +# +# Initial Contributors: +# Nokia Corporation - initial contribution. +# +# Contributors: +# +# Description: +# Routines involved in checking that source matches various filename policy constraints +# +# + + +package CheckSource; + +require Exporter; +@ISA=qw(Exporter); + +# Exported for clarity in calling scripts and modules +our $CheckSource_PhysicalCheck = 1; +our $CheckSource_NoUserSystemDistinction = 1; + +@EXPORT=qw( + CheckSource_MetaData + CheckSource_Includes + CheckSource_ExportedIncludes + CheckSource_MakefileOutput + CheckSource_UnixSlash + CheckSource_Lowercase + CheckSource_Physical + $CheckSource_PhysicalCheck + $CheckSource_NoUserSystemDistinction +); + +use Cwd; +use Pathutl; +use Win32; + +my $exclusionsFile = $ENV{EPOCROOT}."epoc32\\tools\\filenamepolicyexclusions.txt"; + +my $makefileWarningPrefix = "\@echo "; +my $checksourcePrefix = "\@perl -S checksource.pl"; +my $releaseLocationRoot = quotemeta ($ENV{EPOCROOT}."epoc32"); + + +sub CheckSource_MetaData (\%$$$$;$;$) + { + my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $physical, $offset) = @_; + + return if ($reference =~ /^(\.|\.\.)$/); + + my $checksourceCall = "$checksourcePrefix --metadata \"$sourceFile\" \"$item\" \"$reference\" $lineNumber"; + $checksourceCall .= " $physical" if ($physical); + $checksourceCall .= " \"$offset\"" if ($offset); + $$actionHash{$checksourceCall} = 1; + } + + +sub CheckSource_UnixSlash (\%$$$$;$) + { + my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $verbose) = @_; + + $sourceFile =~ s/^[a-zA-Z]{1}://; + $item =~ s/PRJ_EXPORTS \(NO DESTINATION\)/PRJ_EXPORTS/; + + print "Checking - Unix slash : $sourceFile ($lineNumber) - $item:$reference\n" if ($verbose); + + if ($reference =~/\\/) + { + $$actionHash{constructWarning ($sourceFile, $lineNumber, $item, "Incorrect slash in", $reference)} = 1; + } + } + + +sub CheckSource_Lowercase (\%$$$;$;$) + { + my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $verbose) = @_; + + return if ($reference =~ /^[\/|\\]epoc32[\/|\\]tools[\/|\\].*$/); + + $sourceFile =~ s/^[a-zA-Z]{1}://; + + print "Checking - lowercase : $sourceFile ($lineNumber) - $item:$reference\n" if ($verbose); + + my $exclusion = lowercaseExclusionCheck ($reference); + + if ($exclusion eq "UNLISTED") + { + if ($reference =~ /[A-Z]/) + { + $$actionHash{constructWarning ($sourceFile, $lineNumber, $item, "Incorrect case for epoc32 tree in", $reference)} = 1; + } + } + elsif ($exclusion !~ /(OK|ERROR)/) + { + $$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Incorrect case versus exclusion list in", $reference, " vs. $exclusion")} = 1; + } + } + + +sub CheckSource_Physical (\%$$$$;$;$) + { + my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $path, $verbose) = @_; + + print "Checking - physical : $sourceFile ($lineNumber) - $item:$reference:$path\n" if ($verbose); + + my $physicalCheck; + my $searchText; + + my $examineDefaultExportDestination = ($item =~ s/PRJ_EXPORTS \(NO DESTINATION\)/PRJ_EXPORTS/) ? 1 : 0; + + if ($item eq "#include") + { + # In the case of #includes, the path passed in is already the fully pathed physical file + # that needs to be checked (as obtained from the parsed output of CPP) + $searchText = $reference; + $physicalCheck = $path; + } + else + { + my $physicalReference; + if (($item =~ /^PRJ_(TEST)?MMPFILES MMP/) && ($reference !~ /\.\w+$/i)) + { + $physicalReference = $reference."\.mmp"; + $searchText = $reference."\.*"; + } + elsif ($item =~ /^DEFFILE/) + { + # The full path for DEFFILE entries is always passed in, so we just + # need to concentrate on sorting out the oddities for the search + # text and then just take the final file bit as the physical + # reference + + $searchText = $reference; + $searchText .= "?\.*" if ($reference !~ /(\.def|[\\|\/])$/i); + $searchText =~ s/(\.def)/\?$1/i if ($item !~ /NOSTRICTDEF/); + $searchText =~ s/\~/\*/; + $physicalReference = $searchText; + $physicalReference =~ s/\//\\/g; + $physicalReference =~ s/\?/u/; + $physicalReference =~ s/\.\w+$/\.def/; + $physicalReference = &Path_Split ('File', $physicalReference); + } + else + { + $searchText = $reference; + $physicalReference = $searchText; + } + + my $physicalLocation; + if ($path) + { + $physicalLocation = $path; + } + elsif ($reference =~ /^(\\|\/)/) + { + $physicalLocation = $ENV{EPOCROOT}; + } + elsif ($reference =~ /^\+/) + { + $physicalLocation = $ENV{EPOCROOT}."epoc32\\"; + } + elsif ($item =~ /EXTENSIONS/) + { + $physicalLocation = $ENV{EPOCROOT}."epoc32\\tools\\makefile_templates\\"; + } + else + { + $physicalLocation = &Path_Split ('Path', $sourceFile); + } + $physicalReference =~ s/^[\\|\/]//; + $physicalCheck = $physicalLocation.$physicalReference; + } + + $physicalCheck =~ s/\//\\/g; + $physicalCheck = &Path_Strip ($physicalCheck); + + # If a file reference is actually under \epoc32, we just need to confirm that it's lowercase + if ($physicalCheck =~ /^$releaseLocationRoot/i) + { + CheckSource_Lowercase (%$actionHash, $sourceFile, $item, $reference, $lineNumber, $verbose); + return; + } + + # Massage search text to provide something we can compare with a physical check on the filesystem + $searchText =~ s/\//\\/g; + $searchText =~ s/\.\.\\//g; + $searchText =~ s/\.\\//g; + $searchText =~ s/\\\\/\\/g; + + my $warningSearchText = $searchText; # Record a more intelligible version of the search text for warning purposes + + $searchText = quotemeta ($searchText); + $searchText =~ s/\\\*/\\w\+/g; # * -> \w+ + $searchText =~ s/\\\?/\\w\{1\}/g; # ? -> \w{1} + + my $physicalReality = getPhysical ($physicalCheck); + + my $warningSuffix = ""; + + if (!$physicalReality) + { + $$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Can\'t find physical file match for", $reference, " on filesystem")} = 1; + } + elsif ($physicalReality !~ /^.*$searchText$/) + { + if ($physicalReality !~ /^.*$searchText$/i) + { + # Doesn't just differ in case...something's gone wrong + $$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Can\'t find physical file match for", $reference, " - match was attempted against $physicalReality")} = 1; + } + else + { + if (($item =~ /^DEFFILE/ || $item =~ /^PRJ_(TEST)?MMPFILES MMP/) && ($reference !~ /$searchText$/)) + { + $warningSuffix .= " (actual test \'$warningSearchText\')" + } + + $warningSuffix .= " vs. $physicalReality"; + $$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Incorrect case versus filesystem in", $reference, $warningSuffix)} = 1; + } + } + + # Special case - PRJ_EXPORTS source lines with no destination must be normalised via a new destination compliant + # with the filename policy. FIXSOURCE will do this, but it needs a warning to work on + + if ($examineDefaultExportDestination) + { + $physicalReality =~ /^.*($searchText)$/i; + my $defaultExportReference = $1; + + my $exclusion = lowercaseExclusionCheck ($defaultExportReference); + + if ($defaultExportReference =~ /[A-Z]/) + { + $$actionHash{constructWarning ($sourceFile, $lineNumber, $item, "Incorrect case for epoc32 tree from default export in", $reference, $warningSuffix)} = 1; + } + } + + } + + +sub CheckSource_Includes ($\%$\@;\@;\@;$) + { + # References are used for array arguments only so that they can be distinguished within the subroutine + my ($sourceFile, $actionHash, $preInclude, $macros, $userIncludesRef, $systemIncludesRef, $noUserSystemDistinction) = @_; + my (@userIncludes, @systemIncludes); + + @userIncludes = @$userIncludesRef if ($userIncludesRef); + @systemIncludes = @$systemIncludesRef if ($systemIncludesRef); + + my $call = "$checksourcePrefix --preprocess -- "; + + if (($sourceFile !~ /\.inf$/i) && ($sourceFile !~ /\.mmp/i)) + { + push @$macros, "__SUPPORT_CPP_EXCEPTIONS__"; + } + + my $platformPreInclude = ""; + + foreach my $macro (@$macros) + { + $call .= "-D$macro "; + + if ($macro =~ /__ARMCC_2_2__/) + { + $platformPreInclude = $ENV{EPOCROOT}."epoc32\\include\\rvct2_2\\rvct2_2.h"; + + if (($sourceFile =~ /BASE\\E32\\compsupp\\/i) && $ENV{RVCT22INC}) + { + # Need some way to deal with ARMINC from the front-end... + my $rvctIncDir = $ENV{RVCT22INC}; + push @systemIncludes, $rvctIncDir; + } + } + elsif ($macro =~ /__GCCE__/) + { + $platformPreInclude = $ENV{EPOCROOT}."epoc32\\include\\GCCE\\GCCE.h"; + + my $GCCEinstall = Cl_bpabi::getConfigVariable('COMPILER_INSTALL_PATH'); + + push @systemIncludes, "\"\\\"$GCCEinstall\\..\\lib\\gcc\\arm-none-symbianelf\\3.4.3\\include\\\"\""; + } + } + + if ($preInclude ne "") + { + $call .= "-include ".getDrive().$preInclude." "; + push @systemIncludes, &Path_Split ('Path', getDrive().$preInclude); + } + + if ($platformPreInclude ne "") + { + $call .= "-include ".getDrive().$platformPreInclude." "; + push @systemIncludes, &Path_Split ('Path', getDrive().$platformPreInclude); + } + + # Enforce user and system includes in checksource processing. + + foreach my $include (@userIncludes) + { + $include =~ s/\\$//; + $include = getDrive().$include if (($include !~ /^[a-zA-Z]:/) && ($include !~ /^[\"|\.]/)); + $call .= "-I $include "; + } + + $call .= "-I- " unless $noUserSystemDistinction; + + foreach my $include (@systemIncludes) + { + $include =~ s/\\$//; + $include = getDrive().$include if (($include !~ /^[a-zA-Z]:/) && ($include !~ /^[\"|\.]/)); + $call .= "-I $include "; + } + + $sourceFile =~ s/\//\\/g; + $sourceFile = &Path_Strip ($sourceFile); + $sourceFile = getDrive().$sourceFile; + + $call .= $sourceFile; + + $$actionHash{$call} = 1; + + return $call; + } + + +sub CheckSource_ExportedIncludes ($$\%) + { + my ($sourceFile, $destinationFile, $actionHash) = @_; + + # Exclude exported files as appropriate + if ($destinationFile) + { + my $epoc32Include = quotemeta ($ENV{EPOCROOT})."epoc32\\\\include"; + return if ($destinationFile !~ /^$epoc32Include/i); + return if ($destinationFile =~ /\.def$/i); + } + + $$actionHash{"$checksourcePrefix --parsefile -- $sourceFile"} = 1; + } + + +sub CheckSource_MakefileOutput(%) + { + my (%actionHash) = @_; + + return "\t\@rem\n" if !(keys (%actionHash)); + + my $output = ""; + + foreach (keys (%actionHash)) + { + $output .= "\t$_\n"; + } + + return $output; + } + + +sub getDrive + { + if(cwd =~ /^([a-zA-Z]:)/) + { + return $1; + } + + return ""; + } + + +sub getPhysical ($) + { + my ($physicalReference) = @_; + + my $physicalReality = Win32::GetLongPathName($physicalReference); + + if ($physicalReality) + { + $physicalReality =~ s/^.*://; + $physicalReality = &Path_Strip ($physicalReality); + } + + return $physicalReality; + } + + +sub constructWarning ($$$$$;$) + { + my ($sourceFile, $lineNumber, $item, $warningText, $reference, $suffix) = @_; + + $sourceFile =~ s/\//\\/g; + $sourceFile = Win32::GetLongPathName($sourceFile); + $sourceFile =~ s/^[a-zA-Z]{1}://; + $sourceFile = &Path_Strip ($sourceFile); + + my $warning = ""; + $warning .= $sourceFile.":".$lineNumber.": ".$warningText." $item - \'".$reference."\'"; + $warning .= $suffix if ($suffix); + $warning .= "."; + + return $warning; + } + + +sub lowercaseExclusionCheck ($) + { + my ($reference) = @_; + + # An exclusions file isn't mandatory + return "UNLISTED" if (! -e $exclusionsFile); + + my $EXCLUSIONS; + + if (!(open EXCLUSIONS, "< $exclusionsFile")) + { + print ("ERROR: Can't open $exclusionsFile in checksource processing.\n"); + return "ERROR"; + } + + my $referenceDOSSlash = $reference; + $referenceDOSSlash =~ s/\//\\/g; + + my $exclusionCheck = "UNLISTED"; + + while (my $exclusion = ) + { + next if ($exclusion =~ /^\s*$/); + + $exclusion =~ s/^\s+//; + $exclusion =~ s/\s+$//; + $exclusion =~ s/\//\\/g; + my $quotemetaExclusion = quotemeta ($exclusion); + + if ($referenceDOSSlash =~ /^$quotemetaExclusion$/i) + { + if ($referenceDOSSlash !~ /^$quotemetaExclusion$/) + { + $exclusionCheck = $exclusion; + } + else + { + $exclusionCheck = "OK"; + } + last; + } + elsif($referenceDOSSlash =~ /\\$quotemetaExclusion$/i) + { + if ($referenceDOSSlash !~ /\\$quotemetaExclusion$/) + { + $exclusionCheck = $exclusion; + } + else + { + $exclusionCheck = "OK"; + } + last; + } + } + + close EXCLUSIONS; + + return $exclusionCheck; + } + +1;