sbsv1_os/e32toolp/e32util/checksource.pm
changeset 0 83f4b4db085c
child 1 d4b442d23379
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 # Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 # Routines involved in checking that source matches various filename policy constraints
       
    15 # 
       
    16 #
       
    17 
       
    18 
       
    19 package CheckSource;
       
    20 
       
    21 require Exporter;
       
    22 @ISA=qw(Exporter);
       
    23 
       
    24 # Exported for clarity in calling scripts and modules
       
    25 our $CheckSource_PhysicalCheck = 1;
       
    26 our $CheckSource_NoUserSystemDistinction = 1;
       
    27 
       
    28 @EXPORT=qw(
       
    29 	CheckSource_MetaData
       
    30 	CheckSource_Includes
       
    31 	CheckSource_ExportedIncludes
       
    32 	CheckSource_MakefileOutput
       
    33 	CheckSource_UnixSlash
       
    34 	CheckSource_Lowercase
       
    35 	CheckSource_Physical
       
    36 	$CheckSource_PhysicalCheck
       
    37 	$CheckSource_NoUserSystemDistinction
       
    38 );
       
    39 
       
    40 use strict;
       
    41 use Cwd;
       
    42 use Pathutl;
       
    43 use Win32;
       
    44 
       
    45 my $exclusionsFile = $ENV{EPOCROOT}."epoc32\\tools\\filenamepolicyexclusions.txt";
       
    46 
       
    47 my $makefileWarningPrefix = "\@echo ";
       
    48 my $checksourcePrefix = "\@perl -w -S checksource.pl";
       
    49 my $releaseLocationRoot = quotemeta ($ENV{EPOCROOT}."epoc32");
       
    50 
       
    51 
       
    52 sub CheckSource_MetaData (\%$$$$;$;$)
       
    53 	{
       
    54 	my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $physical, $offset) = @_;
       
    55 
       
    56 	return if ($reference =~ /^(\.|\.\.)$/);
       
    57 
       
    58 	my $checksourceCall = "$checksourcePrefix --metadata \"$sourceFile\" \"$item\" \"$reference\" $lineNumber";
       
    59 	$checksourceCall .= " $physical" if ($physical);
       
    60 	$checksourceCall .= " \"$offset\"" if ($offset);
       
    61 	$$actionHash{$checksourceCall} = 1;
       
    62 	}
       
    63 
       
    64 
       
    65 sub CheckSource_UnixSlash (\%$$$$;$)
       
    66 	{
       
    67 	my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $verbose) = @_;
       
    68 
       
    69 	$sourceFile =~ s/^[a-zA-Z]{1}://;
       
    70 	$item =~ s/PRJ_EXPORTS \(NO DESTINATION\)/PRJ_EXPORTS/;
       
    71 
       
    72 	print "Checking - Unix slash : $sourceFile ($lineNumber) - $item:$reference\n" if ($verbose);
       
    73 
       
    74 	if ($reference =~/\\/)
       
    75 		{	
       
    76 		$$actionHash{constructWarning ($sourceFile, $lineNumber, $item, "Incorrect slash in", $reference)} = 1;
       
    77 		}
       
    78 	}
       
    79 
       
    80 
       
    81 sub CheckSource_Lowercase (\%$$$;$;$)
       
    82 	{
       
    83 	my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $verbose) = @_;
       
    84 
       
    85 	return if ($reference =~ /^[\/|\\]epoc32[\/|\\]tools[\/|\\].*$/);
       
    86 
       
    87 	$sourceFile =~ s/^[a-zA-Z]{1}://;
       
    88 
       
    89 	print "Checking - lowercase  : $sourceFile ($lineNumber) - $item:$reference\n" if ($verbose);
       
    90 
       
    91 	my $exclusion = lowercaseExclusionCheck ($reference);
       
    92 
       
    93 	if ($exclusion eq "UNLISTED")
       
    94 		{
       
    95 		if ($reference =~ /[A-Z]/)
       
    96 			{			
       
    97 			$$actionHash{constructWarning ($sourceFile, $lineNumber, $item, "Incorrect case for epoc32 tree in", $reference)} = 1;
       
    98 			}
       
    99 		}
       
   100 	elsif ($exclusion !~ /(OK|ERROR)/)
       
   101 		{
       
   102 		$$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Incorrect case versus exclusion list in", $reference, " vs. $exclusion")} = 1;		
       
   103 		}
       
   104 	}
       
   105 
       
   106 
       
   107 sub CheckSource_Physical (\%$$$$;$;$)
       
   108 	{
       
   109 	my ($actionHash, $sourceFile, $item, $reference, $lineNumber, $path, $verbose) = @_;
       
   110 	
       
   111 	print "Checking - physical   : $sourceFile ($lineNumber) - $item:$reference:$path\n" if ($verbose);
       
   112 
       
   113 	my $physicalCheck;
       
   114 	my $searchText;
       
   115 
       
   116 	my $examineDefaultExportDestination = ($item =~ s/PRJ_EXPORTS \(NO DESTINATION\)/PRJ_EXPORTS/) ? 1 : 0;
       
   117 
       
   118 	if ($item eq "#include")
       
   119 		{
       
   120 		# In the case of #includes, the path passed in is already the fully pathed physical file
       
   121 		# that needs to be checked (as obtained from the parsed output of CPP)
       
   122 		$searchText = $reference;
       
   123 		$physicalCheck = $path;
       
   124 		}
       
   125 	else
       
   126 		{
       
   127 		my $physicalReference;
       
   128 		if (($item =~ /^PRJ_(TEST)?MMPFILES MMP/) && ($reference !~ /\.\w+$/i))
       
   129 			{
       
   130 			$physicalReference = $reference."\.mmp";
       
   131 			$searchText = $reference."\.*";
       
   132 			}
       
   133 		elsif ($item =~ /^DEFFILE/)
       
   134 			{
       
   135 			# The full path for DEFFILE entries is always passed in, so we just
       
   136 			# need to concentrate on sorting out the oddities for the search
       
   137 			# text and then just take the final file bit as the physical
       
   138 			# reference
       
   139 
       
   140 			$searchText = $reference;			
       
   141 			$searchText .= "?\.*" if ($reference !~ /(\.def|[\\|\/])$/i);
       
   142 			$searchText =~ s/(\.def)/\?$1/i if ($item !~ /NOSTRICTDEF/);
       
   143 			$searchText =~ s/\~/\*/;			
       
   144 			$physicalReference = $searchText;
       
   145 			$physicalReference =~ s/\//\\/g;
       
   146 			$physicalReference =~ s/\?/u/;
       
   147 			$physicalReference =~ s/\.\w+$/\.def/;
       
   148 			$physicalReference = &Path_Split ('File', $physicalReference);			
       
   149 			}
       
   150 		else
       
   151 			{
       
   152 			$searchText = $reference;
       
   153 			$physicalReference = $searchText;
       
   154 			}
       
   155 
       
   156 		my $physicalLocation;
       
   157 		if ($path)
       
   158 			{
       
   159 			$physicalLocation = $path;
       
   160 			}
       
   161 		elsif ($reference =~ /^(\\|\/)/)
       
   162 			{
       
   163 			$physicalLocation = $ENV{EPOCROOT};
       
   164 			}
       
   165 		elsif ($reference =~ /^\+/)
       
   166 			{
       
   167 			$physicalLocation = $ENV{EPOCROOT}."epoc32\\";
       
   168 			}
       
   169 		elsif ($item =~ /EXTENSIONS/)
       
   170 			{
       
   171 			$physicalLocation = $ENV{EPOCROOT}."epoc32\\tools\\makefile_templates\\";
       
   172 			}
       
   173 		else
       
   174 			{
       
   175 			$physicalLocation = &Path_Split ('Path', $sourceFile);
       
   176 			}
       
   177 		$physicalReference =~ s/^[\\|\/]//;
       
   178 		$physicalCheck = $physicalLocation.$physicalReference;
       
   179 		}
       
   180 
       
   181 	$physicalCheck =~ s/\//\\/g;
       
   182 	$physicalCheck = &Path_Strip ($physicalCheck);
       
   183 
       
   184 	# If a file reference is actually under \epoc32, we just need to confirm that it's lowercase
       
   185 	if ($physicalCheck =~ /^$releaseLocationRoot/i)
       
   186 		{
       
   187 		CheckSource_Lowercase (%$actionHash, $sourceFile, $item, $reference, $lineNumber, $verbose);
       
   188 		return;
       
   189 		}
       
   190 
       
   191 	# Massage search text to provide something we can compare with a physical check on the filesystem
       
   192 	$searchText =~ s/\//\\/g;
       
   193 	$searchText =~ s/\.\.\\//g;
       
   194 	$searchText =~ s/\.\\//g;
       
   195 	$searchText =~ s/\\\\/\\/g;
       
   196 
       
   197 	my $warningSearchText = $searchText;	# Record a more intelligible version of the search text for warning purposes
       
   198 	
       
   199 	$searchText = quotemeta ($searchText);
       
   200 	$searchText =~ s/\\\*/\\w\+/g;			# * -> \w+
       
   201 	$searchText =~ s/\\\?/\\w\{1\}/g;		# ? -> \w{1}
       
   202 
       
   203 	my $physicalReality = getPhysical ($physicalCheck);
       
   204 
       
   205 	my $warningSuffix = "";
       
   206 
       
   207 	if (!$physicalReality)
       
   208 		{
       
   209 		$$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Can\'t find physical file match for", $reference, " on filesystem")} = 1;
       
   210 		}
       
   211 	elsif ($physicalReality !~ /^.*$searchText$/)
       
   212 		{
       
   213 		if ($physicalReality !~ /^.*$searchText$/i)
       
   214 			{
       
   215 			# Doesn't just differ in case...something's gone wrong
       
   216 			$$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Can\'t find physical file match for", $reference, " - match was attempted against $physicalReality")} = 1;		
       
   217 			}
       
   218 		else
       
   219 			{
       
   220 			if (($item =~ /^DEFFILE/ || $item =~ /^PRJ_(TEST)?MMPFILES MMP/) && ($reference !~ /$searchText$/))
       
   221 				{
       
   222 				$warningSuffix .= " (actual test \'$warningSearchText\')"
       
   223 				}
       
   224 
       
   225 			$warningSuffix .= " vs. $physicalReality";
       
   226 			$$actionHash{constructWarning($sourceFile, $lineNumber, $item, "Incorrect case versus filesystem in", $reference, $warningSuffix)} = 1;
       
   227 			}
       
   228 		}
       
   229 
       
   230 	# Special case - PRJ_EXPORTS source lines with no destination must be normalised via a new destination compliant
       
   231 	# with the filename policy.  FIXSOURCE will do this, but it needs a warning to work on
       
   232 
       
   233 	if ($examineDefaultExportDestination)
       
   234 		{
       
   235 		$physicalReality =~ /^.*($searchText)$/i;
       
   236 		my $defaultExportReference = $1;
       
   237 		
       
   238 		my $exclusion = lowercaseExclusionCheck ($defaultExportReference);
       
   239 
       
   240 		if ($defaultExportReference =~ /[A-Z]/)
       
   241 			{
       
   242 			$$actionHash{constructWarning ($sourceFile, $lineNumber, $item, "Incorrect case for epoc32 tree from default export in", $reference, $warningSuffix)} = 1;
       
   243 			}
       
   244 		}
       
   245 
       
   246 	}
       
   247 	
       
   248 
       
   249 sub CheckSource_Includes ($\%$\@;\@;\@;$)
       
   250 	{
       
   251 	# References are used for array arguments only so that they can be distinguished within the subroutine
       
   252 	my ($sourceFile, $actionHash, $preInclude, $macros, $userIncludesRef, $systemIncludesRef, $noUserSystemDistinction) = @_;
       
   253 	my (@userIncludes, @systemIncludes);
       
   254 
       
   255 	@userIncludes = @$userIncludesRef if ($userIncludesRef);
       
   256 	@systemIncludes = @$systemIncludesRef if ($systemIncludesRef);
       
   257 
       
   258 	my $call = "$checksourcePrefix --preprocess -- ";
       
   259 
       
   260 	if (($sourceFile !~ /\.inf$/i) && ($sourceFile !~ /\.mmp/i))
       
   261 		{
       
   262 		push @$macros, "__SUPPORT_CPP_EXCEPTIONS__";
       
   263 		}
       
   264 
       
   265 	my $platformPreInclude = "";
       
   266 
       
   267 	foreach my $macro (@$macros)
       
   268 		{
       
   269 		$call .= "-D$macro ";
       
   270 
       
   271 		if ($macro =~ /__ARMCC_2_2__/)
       
   272 			{
       
   273 			$platformPreInclude = $ENV{EPOCROOT}."epoc32\\include\\rvct2_2\\rvct2_2.h";
       
   274 
       
   275 			if (($sourceFile =~ /BASE\\E32\\compsupp\\/i) && $ENV{RVCT22INC})
       
   276 				{					
       
   277 				# Need some way to deal with ARMINC from the front-end...
       
   278 				my $rvctIncDir = $ENV{RVCT22INC};
       
   279 				push @systemIncludes, $rvctIncDir;
       
   280 				}
       
   281 			}
       
   282 		elsif ($macro =~ /__GCCE__/)
       
   283 			{
       
   284 			$platformPreInclude = $ENV{EPOCROOT}."epoc32\\include\\GCCE\\GCCE.h";
       
   285 
       
   286 			my $GCCEinstall = Cl_bpabi::getConfigVariable('COMPILER_INSTALL_PATH');
       
   287 			
       
   288 			push @systemIncludes, "\"\\\"$GCCEinstall\\..\\lib\\gcc\\arm-none-symbianelf\\3.4.3\\include\\\"\"";
       
   289 			}
       
   290 		}
       
   291 
       
   292 	if ($preInclude ne "")
       
   293 		{
       
   294 		$call .= "-include ".getDrive().$preInclude." ";
       
   295 		push @systemIncludes, &Path_Split ('Path', getDrive().$preInclude);
       
   296 		}		
       
   297 
       
   298 	if ($platformPreInclude ne "")
       
   299 		{
       
   300 		$call .= "-include ".getDrive().$platformPreInclude." ";
       
   301 		push @systemIncludes, &Path_Split ('Path', getDrive().$platformPreInclude);
       
   302 		}	
       
   303 
       
   304 	# Enforce user and system includes in checksource processing.
       
   305 
       
   306 	foreach my $include (@userIncludes)
       
   307 		{
       
   308 		$include =~ s/\\$//;
       
   309 		$include = getDrive().$include if (($include !~ /^[a-zA-Z]:/) && ($include !~ /^[\"|\.]/));
       
   310 		$call .= "-I $include ";
       
   311 		}
       
   312 
       
   313 	$call .= "-I- " unless $noUserSystemDistinction;
       
   314 
       
   315 	foreach my $include (@systemIncludes)
       
   316 		{
       
   317 		$include =~ s/\\$//;
       
   318 		$include = getDrive().$include if (($include !~ /^[a-zA-Z]:/) && ($include !~ /^[\"|\.]/));
       
   319 		$call .= "-I $include ";
       
   320 		}
       
   321 
       
   322 	$sourceFile =~ s/\//\\/g;
       
   323 	$sourceFile = &Path_Strip ($sourceFile);
       
   324 	$sourceFile = getDrive().$sourceFile;
       
   325 
       
   326 	$call .= $sourceFile;
       
   327 
       
   328 	$$actionHash{$call} = 1;
       
   329 
       
   330 	return $call;
       
   331 	}
       
   332 
       
   333 
       
   334 sub CheckSource_ExportedIncludes ($$\%)
       
   335 	{
       
   336 	my ($sourceFile, $destinationFile, $actionHash) = @_;
       
   337 
       
   338 	# Exclude exported files as appropriate
       
   339 	if ($destinationFile)
       
   340 		{
       
   341 		my $epoc32Include = quotemeta ($ENV{EPOCROOT})."epoc32\\\\include";
       
   342 		return if ($destinationFile !~ /^$epoc32Include/i);
       
   343 		return if ($destinationFile =~ /\.def$/i);
       
   344 		}
       
   345 
       
   346 	$$actionHash{"$checksourcePrefix --parsefile -- $sourceFile"} = 1;
       
   347 	}
       
   348 
       
   349 
       
   350 sub CheckSource_MakefileOutput(%)
       
   351 	{
       
   352 	my (%actionHash) = @_;
       
   353 
       
   354 	return "\t\@rem\n" if !(keys (%actionHash));
       
   355 
       
   356 	my $output = "";
       
   357 
       
   358 	foreach (keys (%actionHash))
       
   359 		{
       
   360 		$output .= "\t$_\n";
       
   361 		}
       
   362 
       
   363 	return $output;
       
   364 	}
       
   365 	
       
   366 
       
   367 sub getDrive
       
   368 	{
       
   369     if(cwd =~ /^([a-zA-Z]:)/)
       
   370     	{
       
   371 		return $1;
       
   372     	}
       
   373 
       
   374 	return "";
       
   375 	}
       
   376 
       
   377 
       
   378 sub getPhysical ($)
       
   379 	{
       
   380 	my ($physicalReference) = @_;
       
   381 	
       
   382 	my $physicalReality = Win32::GetLongPathName($physicalReference);
       
   383 
       
   384 	if ($physicalReality)
       
   385 		{			
       
   386 		$physicalReality =~ s/^.*://;
       
   387 		$physicalReality = &Path_Strip ($physicalReality);		
       
   388 		}
       
   389 
       
   390 	return $physicalReality;
       
   391 	}
       
   392 
       
   393 
       
   394 sub constructWarning ($$$$$;$)
       
   395 	{
       
   396 	my ($sourceFile, $lineNumber, $item, $warningText, $reference, $suffix) = @_;
       
   397 
       
   398 	$sourceFile =~ s/\//\\/g;
       
   399 	$sourceFile = Win32::GetLongPathName($sourceFile);
       
   400 	$sourceFile =~ s/^[a-zA-Z]{1}://;
       
   401 	$sourceFile = &Path_Strip ($sourceFile);
       
   402 
       
   403 	my $warning = "";
       
   404 	$warning .= $sourceFile.":".$lineNumber.": ".$warningText." $item - \'".$reference."\'";
       
   405 	$warning .= $suffix if ($suffix);
       
   406 	$warning .= ".";		
       
   407 
       
   408 	return $warning;
       
   409 	}
       
   410 
       
   411 
       
   412 sub lowercaseExclusionCheck ($)
       
   413 	{
       
   414 	my ($reference) = @_;
       
   415 
       
   416 	# An exclusions file isn't mandatory
       
   417 	return "UNLISTED" if (! -e $exclusionsFile);
       
   418 
       
   419 	my $EXCLUSIONS;
       
   420 
       
   421 	if (!(open EXCLUSIONS, "< $exclusionsFile"))
       
   422 			{
       
   423 			print ("ERROR: Can't open $exclusionsFile in checksource processing.\n");
       
   424 			return "ERROR";
       
   425 			}
       
   426 
       
   427 	my $referenceDOSSlash = $reference;
       
   428 	$referenceDOSSlash =~ s/\//\\/g;
       
   429 
       
   430 	my $exclusionCheck = "UNLISTED";
       
   431 
       
   432 	while (my $exclusion = <EXCLUSIONS>)
       
   433 		{
       
   434 		next if ($exclusion =~ /^\s*$/);
       
   435 
       
   436 		$exclusion =~ s/^\s+//;
       
   437 		$exclusion =~ s/\s+$//;
       
   438 		$exclusion =~ s/\//\\/g;
       
   439 		my $quotemetaExclusion = quotemeta ($exclusion);
       
   440 
       
   441 		if ($referenceDOSSlash =~ /^$quotemetaExclusion$/i)
       
   442 			{				
       
   443 			if ($referenceDOSSlash !~ /^$quotemetaExclusion$/)
       
   444 				{
       
   445 				$exclusionCheck = $exclusion;
       
   446 				}
       
   447 			else
       
   448 				{
       
   449 				$exclusionCheck = "OK";
       
   450 				}
       
   451 			last;
       
   452 			}
       
   453 			elsif($referenceDOSSlash =~ /\\$quotemetaExclusion$/i)
       
   454 			{				
       
   455 			if ($referenceDOSSlash !~ /\\$quotemetaExclusion$/)
       
   456 				{
       
   457 				$exclusionCheck = $exclusion;
       
   458 				}
       
   459 			else
       
   460 				{
       
   461 				$exclusionCheck = "OK";
       
   462 				}
       
   463 			last;
       
   464 			}
       
   465 		}
       
   466 
       
   467 	close EXCLUSIONS;
       
   468 
       
   469 	return $exclusionCheck;
       
   470 	}
       
   471 
       
   472 1;