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