|
1 @rem |
|
2 @rem Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 @rem All rights reserved. |
|
4 @rem This component and the accompanying materials are made available |
|
5 @rem under the terms of "Eclipse Public License v1.0" |
|
6 @rem which accompanies this distribution, and is available |
|
7 @rem at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 @rem |
|
9 @rem Initial Contributors: |
|
10 @rem Nokia Corporation - initial contribution. |
|
11 @rem |
|
12 @rem Contributors: |
|
13 @rem |
|
14 @rem Description: |
|
15 @rem |
|
16 @rem = '--*-Perl-*-- |
|
17 @echo off |
|
18 if "%OS%" == "Windows_NT" goto WinNT |
|
19 perl -x -S "%0" %1 %2 %3 %4 %5 %6 %7 %8 %9 |
|
20 goto endofperl |
|
21 :WinNT |
|
22 perl -x -S "%0" %* |
|
23 if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endofperl |
|
24 if %errorlevel% == 9009 echo You do not have Perl in your PATH. |
|
25 goto endofperl |
|
26 @rem '; |
|
27 #!perl |
|
28 #line 14 |
|
29 |
|
30 |
|
31 use strict; |
|
32 use Getopt::Long; |
|
33 use File::Spec; |
|
34 use File::Copy; |
|
35 use File::Path; |
|
36 use File::Basename; |
|
37 |
|
38 my $toolVersion = "2.1"; |
|
39 |
|
40 # Example warnings: |
|
41 # |
|
42 # Incorrect slash |
|
43 # \src\common\generic\comms-infras\commsfw\group\bld.inf:10: Incorrect slash in PRJ_EXPORTS - '..\inc\commschan.h'. |
|
44 # \src\cedar\generic\base\f32\group\ecomp.mmp:14: Incorrect slash in SYSTEMINCLUDE - '..\inc'. |
|
45 # \src\common\generic\syncml\framework\TransportProvision\HttpWsp\SmlHttpBase.cpp:13: Incorrect slash in #include - 'http\rhttpheaders.h'. |
|
46 # |
|
47 # Incorrect case for epoc32 tree |
|
48 # \src\common\generic\syslibs\pwrcli\group\bld.inf:23: Incorrect case for epoc32 tree in PRJ_EXPORTS - '\epoc32\rom\include\PwrCli.IBY'. |
|
49 # \src\common\generic\security\crypto\group\hash.mmp:8: Incorrect case for epoc32 tree in TARGET - 'hash.DLL'. |
|
50 # \src\common\generic\syslibs\ecom\ongoing\Framework\frame\Discoverer.cpp:20: Incorrect case for epoc32 tree in #include - 'BaSPI.h'. |
|
51 # |
|
52 # Incorrect case versus filesystem |
|
53 # \src\common\generic\comms-infras\commdb\commdbshim\group\BLD.INF:20: Incorrect case versus filesystem in PRJ_EXPORTS - '..\inc\cdblen.h' vs. \src\common\generic\comms-infras\commdb\commdbshim\INC\CDBLEN.H. |
|
54 # \src\common\generic\syslibs\ecom\ongoing\Framework\MMPFiles\EComServer.mmp:45: Incorrect case versus filesystem in USERINCLUDE - '..\..\framework\inc' vs. \src\common\generic\syslibs\ecom\ongoing\Framework\inc. |
|
55 # \src\common\generic\comms-infras\commdb\commdbshim\INC\CDBOVER.H:16: Incorrect case versus filesystem in #include - 'cdbpreftable.h' vs. \src\common\generic\comms-infras\commdb\commdbshim\INC\CDBPREFTABLE.H. |
|
56 # |
|
57 # Incorrect case for epoc32 tree from default export (i.e. source export case will replicated under \epoc32) |
|
58 # \src\common\generic\application-protocols\http\group\bld.inf:22: Incorrect case for epoc32 tree from default export in PRJ_EXPORTS - '..\inc\HTTPSocketConstants.h'. |
|
59 # \src\common\generic\messaging\email\smtpservermtm\group\bld.inf:11: Incorrect case for epoc32 tree from default export in PRJ_EXPORTS - '..\inc\smts.h' vs. \src\common\generic\messaging\email\smtpservermtm\inc\SMTS.H. |
|
60 # |
|
61 # Incorrect case versus exclusion list |
|
62 # \src\common\generic\Multimedia\openmax\group\bld.inf:14: Incorrect case versus exclusion list in PRJ_EXPORTS - '\epoc32\include\openmax\il\OMX_Types.h' vs. OMX_TYPES.H. |
|
63 # \src\common\generic\Multimedia\openmax\inc\openmax\il\OMX_Audio.h:41: Incorrect case versus exclusion list in #include - 'OMX_Types.h' vs. OMX_TYPES.H. |
|
64 # |
|
65 # Can't find physical file match for |
|
66 # \src\common\generic\app-framework\conarc\group\BLD.INF:48: Can't find physical file match for PRJ_TESTMMPFILES MMP - '..\tsrc\tcon3_V2.mpp' on filesystem. |
|
67 # |
|
68 |
|
69 |
|
70 # 1. Check arguments, output help etc. |
|
71 |
|
72 my $analyse = 0; |
|
73 my $list = 0; |
|
74 my $update = 0; |
|
75 my $warnings = ""; |
|
76 my $verbose = 0; |
|
77 my $debug = 0; |
|
78 my $debugUpdate = 0; |
|
79 GetOptions ('analyse|a' => \$analyse, 'list|l' => \$list, 'update|u' => \$update, 'warnings|w=s' => \$warnings, |
|
80 'verbose|v' => \$verbose, 'debug|d' => \$debug, 'debugupdate|du' => \$debugUpdate); |
|
81 |
|
82 if (@ARGV == 0) |
|
83 { |
|
84 print (STDERR "\nFIXSOURCE.BAT - Version $toolVersion\n"); |
|
85 |
|
86 print STDERR << 'END_OF_HELP'; |
|
87 |
|
88 Usage: fixsource.bat -analyse|-list|-update|-warnings buildlog_1.log [buildlog_n.log] |
|
89 |
|
90 Parses the output from the specified build logs to locate warnings produced via |
|
91 "abld -checksource". Provides the option to update source automatically to comply |
|
92 with Symbian's Filename Policy. |
|
93 |
|
94 -analyse | -a List and describe all warnings that cannot be addressed |
|
95 by this tool. |
|
96 -list | -l List all source files that can be updated by this tool |
|
97 using "-update". |
|
98 -update | -u Update source files, as output by "-list", to comply with |
|
99 Symbian's Filename Policy. |
|
100 -warnings| -w [all|fixable] Output all unique "-checksource" warnings present in the |
|
101 specified logs: |
|
102 all - every warning, regardless of whether this |
|
103 tool can fix them. |
|
104 fixable - only warnings that this tool can fix. |
|
105 -verbose | -v Additional verbose output for the "-update" option. |
|
106 |
|
107 NOTES: |
|
108 * The tool assumes that the original build source and layout is present on the drive |
|
109 where it is being executed. |
|
110 * With the exception of the "-warnings all" output, any warnings for files under the |
|
111 known release and build locations of %EPOCROOT%epoc32\include and |
|
112 %EPOCROOT%epoc32\build are discarded by default. |
|
113 |
|
114 END_OF_HELP |
|
115 |
|
116 } |
|
117 |
|
118 |
|
119 # 2. Parse the logs storing all GNU format warnings and errors |
|
120 |
|
121 |
|
122 my %ActionableFilenamePolicyWarnings; # Hash Key (filename) |
|
123 # Hash Key (line number) |
|
124 # Hash Key (problematic text) |
|
125 # Hash Key ORIGINAL_WARNINGS |
|
126 # Hash Key (original warning) |
|
127 # 1 |
|
128 # Hash Key ITEM |
|
129 # item type that has generated the warning |
|
130 # Hash Key SEARCH_TEXT |
|
131 # quotemeta version of problematic text |
|
132 # Hash Key UNIX_SLASH |
|
133 # 1 |
|
134 # Hash Key LOWERCASE |
|
135 # 1 |
|
136 # Hash Key PHYSICAL |
|
137 # 1 |
|
138 # Hash Key EXCLUSION |
|
139 # 1 |
|
140 # Hash Key PHYSICAL_REALITY |
|
141 # Hash Key (physical reality) |
|
142 # 1 |
|
143 # fully pathed filesystem reality used in physical checking |
|
144 # Hash Key EXCLUSION_LISTING |
|
145 # required format of reference as dictated from an exclusion list |
|
146 # Hash Key ACTUAL_TEST |
|
147 # test used for check when this differed from that in actual source |
|
148 # Hash Key DEFAULT_EXPORT |
|
149 # special case - a PRJ_EXPORTS line without a destination will break |
|
150 # the filename policy if the source line is not lowercase |
|
151 my %NonActionableFilenamePolicyWarnings; |
|
152 my %AllFilenamePolicyWarnings; |
|
153 my %OtherWarningsAndErrors; |
|
154 |
|
155 foreach my $BUILD_LOG (@ARGV) |
|
156 { |
|
157 open BUILD_LOG, "< $BUILD_LOG" or die "\nCannot read \"$BUILD_LOG\"!\n\n"; |
|
158 |
|
159 while (<BUILD_LOG>) |
|
160 { |
|
161 chomp; |
|
162 |
|
163 if (/^\\\S+:.*: .+$/) |
|
164 { |
|
165 if (!/:\d+: (Incorrect case|Incorrect slash|Can\'t find) /) |
|
166 { |
|
167 $OtherWarningsAndErrors{$_} = 1 if (!/(unresolved api-item|unknown base class|unresolved xref|no image file|xm-replace_text)/); # Ignore the noise of doc stuff... |
|
168 next; |
|
169 } |
|
170 |
|
171 $AllFilenamePolicyWarnings{$_} = 1; |
|
172 |
|
173 if (/: Can\'t find /) |
|
174 { |
|
175 $NonActionableFilenamePolicyWarnings{$_} = 1; |
|
176 next; |
|
177 } |
|
178 |
|
179 my $originalWarning = $_; |
|
180 |
|
181 /(^.*):(\d+): Incorrect (case for epoc32 tree|case versus filesystem|case versus exclusion list|slash|case for epoc32 tree from default export) in (.+) - \'(.+?)\'/; |
|
182 |
|
183 my $filename = $1; |
|
184 my $lineNumber = $2; |
|
185 my $type = $3; |
|
186 my $item = $4; |
|
187 my $problematicText = $5; |
|
188 |
|
189 $type =~ s/case for epoc32 tree from default export/defaultexport/; |
|
190 $type =~ s/case for epoc32 tree/lowercase/; |
|
191 $type =~ s/case versus filesystem/physical/; |
|
192 $type =~ s/case versus exclusion list/exclusion/; |
|
193 |
|
194 my $actualTest = ""; |
|
195 my $physicalReality = ""; |
|
196 my $exclusionListing = ""; |
|
197 $actualTest = $1 if (/\(actual test \'(.*)\'\)/); |
|
198 |
|
199 if (/ vs\. (.*)\./) |
|
200 { |
|
201 $physicalReality = $1 if ($type eq "physical"); |
|
202 $exclusionListing = $1 if ($type eq "exclusion"); |
|
203 } |
|
204 |
|
205 if ($debug) |
|
206 { |
|
207 print ("ORIGINAL WARNING : $originalWarning\n"); |
|
208 print ("FILENAME : $filename\n"); |
|
209 print ("LINENUMBER : $lineNumber\n"); |
|
210 print ("TYPE : $type\n"); |
|
211 print ("ITEM : $item\n"); |
|
212 print ("PROBLEMATIC TEXT : $problematicText\n"); |
|
213 print ("ACTUAL TEST : $actualTest\n") if ($actualTest); |
|
214 print ("PHYSICAL REALITY : $physicalReality\n") if ($physicalReality); |
|
215 print ("EXCLUSION LISTING : $exclusionListing\n") if ($exclusionListing); |
|
216 print ("\n"); |
|
217 } |
|
218 |
|
219 next if ($warnings =~ /all/i); |
|
220 |
|
221 # Line Number |
|
222 |
|
223 my $lineNumberHashRef; |
|
224 if ($ActionableFilenamePolicyWarnings{$filename}) |
|
225 { |
|
226 $lineNumberHashRef = $ActionableFilenamePolicyWarnings{$filename}; |
|
227 } |
|
228 else |
|
229 { |
|
230 my %newHash; |
|
231 $lineNumberHashRef = \%newHash; |
|
232 $ActionableFilenamePolicyWarnings{$filename} = $lineNumberHashRef; |
|
233 } |
|
234 |
|
235 # Problematic Text |
|
236 |
|
237 my $problematicTextHashRef; |
|
238 if ($lineNumberHashRef->{$lineNumber}) |
|
239 { |
|
240 $problematicTextHashRef = $lineNumberHashRef->{$lineNumber}; |
|
241 } |
|
242 else |
|
243 { |
|
244 my %newHash; |
|
245 $problematicTextHashRef = \%newHash; |
|
246 $lineNumberHashRef->{$lineNumber} = $problematicTextHashRef; |
|
247 } |
|
248 |
|
249 # Attributes |
|
250 |
|
251 my $attributesHashRef; |
|
252 if ($problematicTextHashRef->{$problematicText}) |
|
253 { |
|
254 $attributesHashRef = $problematicTextHashRef->{$problematicText}; |
|
255 } |
|
256 else |
|
257 { |
|
258 my %newHash; |
|
259 $attributesHashRef = \%newHash; |
|
260 $problematicTextHashRef->{$problematicText} = $attributesHashRef; |
|
261 } |
|
262 |
|
263 # Attributes : Original Warnings |
|
264 |
|
265 my $originalWarningsHashRef; |
|
266 if ($attributesHashRef->{ORIGINAL_WARNINGS}) |
|
267 { |
|
268 $originalWarningsHashRef = $attributesHashRef->{ORIGINAL_WARNINGS}; |
|
269 } |
|
270 else |
|
271 { |
|
272 my %newHash; |
|
273 $originalWarningsHashRef = \%newHash; |
|
274 $attributesHashRef->{ORIGINAL_WARNINGS} = $originalWarningsHashRef; |
|
275 } |
|
276 $originalWarningsHashRef->{$originalWarning} = 1; |
|
277 |
|
278 # Attributes : Item |
|
279 |
|
280 $attributesHashRef->{ITEM} = $item; |
|
281 |
|
282 # Attributes : Search Text |
|
283 |
|
284 $attributesHashRef->{SEARCH_TEXT} = quotemeta ($problematicText); |
|
285 |
|
286 # Attributes : Unix Slash |
|
287 |
|
288 $attributesHashRef->{UNIX_SLASH} = 1 if ($type eq "slash"); |
|
289 |
|
290 # Attributes : Lowercase |
|
291 |
|
292 $attributesHashRef->{LOWERCASE} = 1 if ($type eq "lowercase"); |
|
293 |
|
294 # Attributes : Physical |
|
295 |
|
296 $attributesHashRef->{PHYSICAL} = 1 if ($type eq "physical"); |
|
297 |
|
298 # Attributes : Exclusion |
|
299 |
|
300 $attributesHashRef->{EXCLUSION} = 1 if ($type eq "exclusion"); |
|
301 |
|
302 # Attributes : Physical Reality |
|
303 |
|
304 my $physicalRealityHashRef; |
|
305 if ($physicalReality) |
|
306 { |
|
307 if ($attributesHashRef->{PHYSICAL_REALITY}) |
|
308 { |
|
309 $physicalRealityHashRef = $attributesHashRef->{PHYSICAL_REALITY}; |
|
310 } |
|
311 else |
|
312 { |
|
313 my %newHash; |
|
314 $physicalRealityHashRef = \%newHash; |
|
315 $attributesHashRef->{PHYSICAL_REALITY} = $physicalRealityHashRef; |
|
316 } |
|
317 $physicalRealityHashRef->{$physicalReality} = 1; |
|
318 } |
|
319 |
|
320 # Attributes : Actual Test |
|
321 |
|
322 $attributesHashRef->{ACTUAL_TEST} = $actualTest if ($actualTest); |
|
323 |
|
324 # Attributes : Exclusion Listing |
|
325 |
|
326 $attributesHashRef->{EXCLUSION_LISTING} = $exclusionListing if ($exclusionListing); |
|
327 |
|
328 # Attributes : Default Export |
|
329 |
|
330 $attributesHashRef->{DEFAULT_EXPORT} = 1 if ($type eq "defaultexport"); |
|
331 } |
|
332 } |
|
333 |
|
334 close BUILD_LOG; |
|
335 } |
|
336 |
|
337 |
|
338 # 3. Examine source and warnings and compile lists of files and warnings that we can/can't do anything about |
|
339 |
|
340 my %WarningsNotMatchingSource; |
|
341 my %WarningsWithMissingFiles; |
|
342 my %WarningsForBothLowercaseAndPhysicalOnSameReference; |
|
343 my %WarningsForMultiplePhysicalUpdates; |
|
344 |
|
345 |
|
346 if ($analyse || $list || $update || $debugUpdate || $warnings =~ /^fixable$/i) |
|
347 { |
|
348 |
|
349 foreach my $SOURCE_FILE (sort keys %ActionableFilenamePolicyWarnings) |
|
350 { |
|
351 |
|
352 # Discard anything in known release locations |
|
353 |
|
354 if ($SOURCE_FILE =~ /\\epoc32\\(include|build)\\/i) |
|
355 { |
|
356 delete ($ActionableFilenamePolicyWarnings{$SOURCE_FILE}); |
|
357 next; |
|
358 } |
|
359 |
|
360 my $lineNumbersHashRef = $ActionableFilenamePolicyWarnings{$SOURCE_FILE}; |
|
361 |
|
362 # Discard warnings where source files cannot be found |
|
363 |
|
364 if (!(open SOURCE_FILE, "< $SOURCE_FILE")) |
|
365 { |
|
366 foreach my $lineNumber (sort keys (%$lineNumbersHashRef)) |
|
367 { |
|
368 my $problematicTextHashRef = $lineNumbersHashRef->{$lineNumber}; |
|
369 |
|
370 foreach my $problematicText (sort keys (%$problematicTextHashRef)) |
|
371 { |
|
372 my $attributesHashRef = $problematicTextHashRef->{$problematicText}; |
|
373 my $originalWarningsHashRef = $attributesHashRef->{ORIGINAL_WARNINGS}; |
|
374 |
|
375 foreach my $originalWarning (keys (%$originalWarningsHashRef)) |
|
376 { |
|
377 $WarningsWithMissingFiles{$originalWarning} = 1; |
|
378 } |
|
379 } |
|
380 } |
|
381 delete ($ActionableFilenamePolicyWarnings{$SOURCE_FILE}); |
|
382 next; |
|
383 } |
|
384 |
|
385 |
|
386 # Identify and discard warnings where, for the same reference: |
|
387 # (a) both lowercase and physical warnings are flagged and |
|
388 # (b) multiple, different, filesystem matches have been found |
|
389 # These will need to be resolved manually |
|
390 |
|
391 foreach my $lineNumber (sort keys (%$lineNumbersHashRef)) |
|
392 { |
|
393 my $problematicTextHashRef = $lineNumbersHashRef->{$lineNumber}; |
|
394 |
|
395 foreach my $problematicText (sort keys (%$problematicTextHashRef)) |
|
396 { |
|
397 my $attributesHashRef = $problematicTextHashRef->{$problematicText}; |
|
398 my $originalWarningsHashRef = $attributesHashRef->{ORIGINAL_WARNINGS}; |
|
399 |
|
400 my $skipPhysicalUpdate = 0; |
|
401 my $skipLowercaseUpdate = 0; |
|
402 |
|
403 if ($attributesHashRef->{LOWERCASE} && $attributesHashRef->{PHYSICAL}) |
|
404 { |
|
405 $skipPhysicalUpdate = 1; |
|
406 $skipLowercaseUpdate = 1; |
|
407 |
|
408 foreach my $originalWarning (keys %{$originalWarningsHashRef}) |
|
409 { |
|
410 next if ($originalWarning !~ /Incorrect case/); |
|
411 |
|
412 $originalWarning =~ /\:(.*$)/; |
|
413 |
|
414 my $lowercaseAndPhysicalWarningsHashRef; |
|
415 if ($WarningsForBothLowercaseAndPhysicalOnSameReference{$SOURCE_FILE}) |
|
416 { |
|
417 $lowercaseAndPhysicalWarningsHashRef = $WarningsForBothLowercaseAndPhysicalOnSameReference{$SOURCE_FILE}; |
|
418 } |
|
419 else |
|
420 { |
|
421 my %newHash; |
|
422 $lowercaseAndPhysicalWarningsHashRef = \%newHash; |
|
423 $WarningsForBothLowercaseAndPhysicalOnSameReference{$SOURCE_FILE} = $lowercaseAndPhysicalWarningsHashRef; |
|
424 } |
|
425 $lowercaseAndPhysicalWarningsHashRef->{$1} = 1; |
|
426 } |
|
427 } |
|
428 |
|
429 my $physicalRealityHashRef = $attributesHashRef->{PHYSICAL_REALITY}; |
|
430 |
|
431 if ($physicalRealityHashRef && ((keys %{$physicalRealityHashRef}) > 1)) |
|
432 { |
|
433 my $physicalMatchCheck; |
|
434 if ($attributesHashRef->{ACTUAL_TEST}) |
|
435 { |
|
436 $physicalMatchCheck = $attributesHashRef->{ACTUAL_TEST}; |
|
437 } |
|
438 else |
|
439 { |
|
440 $physicalMatchCheck = $problematicText; |
|
441 $physicalMatchCheck =~ s/\.\.[\\|\/]//g; |
|
442 $physicalMatchCheck =~ s/\.[\\|\/]//g; |
|
443 } |
|
444 |
|
445 $physicalMatchCheck =~ s/\\\\/\\/g; |
|
446 $physicalMatchCheck =~ s/\/\//\//g; |
|
447 $physicalMatchCheck =~ s/\//\\/g; |
|
448 $physicalMatchCheck = quotemeta($physicalMatchCheck); |
|
449 $physicalMatchCheck =~ s/\\\*/\\w\+/g; # * -> \w+ |
|
450 $physicalMatchCheck =~ s/\\\?/\\w\{1\}/g; # ? -> \w{1} |
|
451 |
|
452 my %normalisedPhysicalReferences; |
|
453 |
|
454 foreach my $physicalReality (keys %{$physicalRealityHashRef}) |
|
455 { |
|
456 $physicalReality =~ /($physicalMatchCheck)$/i; |
|
457 $normalisedPhysicalReferences{$1} = 1; |
|
458 } |
|
459 |
|
460 if ((keys (%normalisedPhysicalReferences)) > 1) |
|
461 { |
|
462 foreach my $originalWarning (keys %{$originalWarningsHashRef}) |
|
463 { |
|
464 next if ($originalWarning !~ /Incorrect case versus/); |
|
465 |
|
466 $originalWarning =~ /\:(.*$)/; |
|
467 |
|
468 my $multiplePhysicalWarningsHashRef; |
|
469 if ($WarningsForMultiplePhysicalUpdates{$SOURCE_FILE}) |
|
470 { |
|
471 $multiplePhysicalWarningsHashRef = $WarningsForMultiplePhysicalUpdates{$SOURCE_FILE}; |
|
472 } |
|
473 else |
|
474 { |
|
475 my %newHash; |
|
476 $multiplePhysicalWarningsHashRef = \%newHash; |
|
477 $WarningsForMultiplePhysicalUpdates{$SOURCE_FILE} = $multiplePhysicalWarningsHashRef; |
|
478 } |
|
479 $multiplePhysicalWarningsHashRef->{$1} = 1; |
|
480 } |
|
481 $skipPhysicalUpdate = 1; |
|
482 } |
|
483 } |
|
484 |
|
485 $attributesHashRef->{LOWERCASE} = 0 if ($skipLowercaseUpdate); |
|
486 $attributesHashRef->{PHYSICAL} = 0 if ($skipPhysicalUpdate); |
|
487 |
|
488 if (!$attributesHashRef->{LOWERCASE} && !$attributesHashRef->{PHYSICAL} && |
|
489 !$attributesHashRef->{UNIX_SLASH} && !$attributesHashRef->{DEFAULT_EXPORT} && |
|
490 !$attributesHashRef->{EXCLUSION}) |
|
491 { |
|
492 delete ($problematicTextHashRef->{$problematicText}); |
|
493 } |
|
494 } |
|
495 |
|
496 delete ($lineNumbersHashRef->{$lineNumber}) if (!scalar (keys %{$problematicTextHashRef})); |
|
497 } |
|
498 |
|
499 my $lineNumber = 0; |
|
500 |
|
501 while (my $line = <SOURCE_FILE>) |
|
502 { |
|
503 $lineNumber++; |
|
504 |
|
505 next if (!($lineNumbersHashRef->{$lineNumber})); |
|
506 |
|
507 my $problematicTextHashRef = $lineNumbersHashRef->{$lineNumber}; |
|
508 |
|
509 foreach my $text (keys %{$problematicTextHashRef}) |
|
510 { |
|
511 my $attributesHashRef = $problematicTextHashRef->{$text}; |
|
512 |
|
513 chomp ($line); |
|
514 |
|
515 if ($line !~ /(\"|\<|^|\s){1}$attributesHashRef->{SEARCH_TEXT}/) |
|
516 { |
|
517 # Put warning(s) onto the failed list, as we can't find the required text |
|
518 # in the source present on the machine |
|
519 |
|
520 my $originalWarningsHashRef = $attributesHashRef->{ORIGINAL_WARNINGS}; |
|
521 foreach my $originalWarning (keys %{$originalWarningsHashRef}) |
|
522 { |
|
523 $WarningsNotMatchingSource{$originalWarning} = $line; |
|
524 } |
|
525 |
|
526 delete ($problematicTextHashRef->{$text}); |
|
527 } |
|
528 } |
|
529 |
|
530 delete ($lineNumbersHashRef->{$lineNumber}) if (!scalar (keys %{$problematicTextHashRef})); |
|
531 } |
|
532 |
|
533 delete ($ActionableFilenamePolicyWarnings{$SOURCE_FILE}) if (!scalar (keys %{$lineNumbersHashRef})); |
|
534 close SOURCE_FILE; |
|
535 } |
|
536 } |
|
537 |
|
538 |
|
539 # 4. Provide -warnings [all|fixable] output |
|
540 |
|
541 if ($warnings =~ /^all$/i) |
|
542 { |
|
543 foreach my $warning (sort keys %AllFilenamePolicyWarnings) |
|
544 { |
|
545 print ("$warning\n"); |
|
546 } |
|
547 } |
|
548 elsif ($warnings =~ /^fixable$/i) |
|
549 { |
|
550 my %fixableWarnings; |
|
551 |
|
552 foreach my $sourceFile (keys %ActionableFilenamePolicyWarnings) |
|
553 { |
|
554 my $lineNumbersHashRef = $ActionableFilenamePolicyWarnings{$sourceFile}; |
|
555 |
|
556 foreach my $lineNumber (keys (%$lineNumbersHashRef)) |
|
557 { |
|
558 my $problematicTextHashRef = $lineNumbersHashRef->{$lineNumber}; |
|
559 |
|
560 foreach my $text (keys %{$problematicTextHashRef}) |
|
561 { |
|
562 my $attributesHashRef = $problematicTextHashRef->{$text}; |
|
563 my $originalWarningsHashRef = $attributesHashRef->{ORIGINAL_WARNINGS}; |
|
564 |
|
565 foreach my $originalWarning (keys %{$originalWarningsHashRef}) |
|
566 { |
|
567 $fixableWarnings{$originalWarning} = 1; |
|
568 } |
|
569 } |
|
570 } |
|
571 } |
|
572 |
|
573 foreach my $fixableWarning (sort keys %fixableWarnings) |
|
574 { |
|
575 print ("$fixableWarning\n"); |
|
576 } |
|
577 } |
|
578 |
|
579 |
|
580 # 5. Provide -list output |
|
581 |
|
582 if ($list) |
|
583 { |
|
584 foreach my $sourceFile (sort keys %ActionableFilenamePolicyWarnings) |
|
585 { |
|
586 print ("$sourceFile\n"); |
|
587 } |
|
588 } |
|
589 |
|
590 |
|
591 # 6. Provide -analyse output |
|
592 |
|
593 if ($analyse) |
|
594 { |
|
595 print ("\nFilename policy warnings with missing files\n". |
|
596 "-------------------------------------------\n\n"); |
|
597 foreach my $warningWithMissingFile (sort keys %WarningsWithMissingFiles) |
|
598 { |
|
599 print ("$warningWithMissingFile\n"); |
|
600 } |
|
601 print ("NONE\n") if (!scalar (keys %WarningsWithMissingFiles)); |
|
602 |
|
603 |
|
604 print ("\n\nFilename policy warnings that don't match source\n". |
|
605 "------------------------------------------------\n\n"); |
|
606 foreach my $warningNotMatchingSource (sort keys %WarningsNotMatchingSource) |
|
607 { |
|
608 print ("$warningNotMatchingSource\n"); |
|
609 print ("\tACTUAL LINE : \'$WarningsNotMatchingSource{$warningNotMatchingSource}\'\n"); |
|
610 } |
|
611 print ("NONE\n") if (!scalar (keys %WarningsNotMatchingSource)); |
|
612 |
|
613 print ("\n\nFilename policy warnings with both lowercase and physical warnings for the same reference\n". |
|
614 "-----------------------------------------------------------------------------------------\n\n"); |
|
615 foreach my $sourceFile (sort keys %WarningsForBothLowercaseAndPhysicalOnSameReference) |
|
616 { |
|
617 print ("$sourceFile\n"); |
|
618 foreach my $warning (sort keys %{$WarningsForBothLowercaseAndPhysicalOnSameReference{$sourceFile}}) |
|
619 { |
|
620 print ("\t$warning\n"); |
|
621 } |
|
622 } |
|
623 print ("NONE\n") if (!scalar (keys %WarningsForBothLowercaseAndPhysicalOnSameReference)); |
|
624 |
|
625 print ("\n\nMultiple differing physical filename policy warnings for the same reference\n". |
|
626 "---------------------------------------------------------------------------\n\n"); |
|
627 foreach my $sourceFile (sort keys %WarningsForMultiplePhysicalUpdates) |
|
628 { |
|
629 print ("$sourceFile\n"); |
|
630 foreach my $warning (sort keys %{$WarningsForMultiplePhysicalUpdates{$sourceFile}}) |
|
631 { |
|
632 print ("\t$warning\n"); |
|
633 } |
|
634 } |
|
635 print ("NONE\n") if (!scalar (keys %WarningsForMultiplePhysicalUpdates)); |
|
636 |
|
637 print ("\n\nNon-actionable filename policy warnings\n". |
|
638 "---------------------------------------\n\n"); |
|
639 foreach my $nonActionableWarning (sort keys %NonActionableFilenamePolicyWarnings) |
|
640 { |
|
641 print ("$nonActionableWarning\n"); |
|
642 } |
|
643 print ("NONE\n") if (!scalar (keys %NonActionableFilenamePolicyWarnings)); |
|
644 |
|
645 |
|
646 print ("\n\nOther detected warnings unrelated to filename policy\n". |
|
647 "----------------------------------------------------\n\n"); |
|
648 foreach my $otherWarningOrError (sort keys %OtherWarningsAndErrors) |
|
649 { |
|
650 print ("$otherWarningOrError\n"); |
|
651 } |
|
652 print ("NONE\n") if (!scalar (keys %OtherWarningsAndErrors)); |
|
653 |
|
654 print ("\n\n"); |
|
655 } |
|
656 |
|
657 |
|
658 # 7. Perform -update function |
|
659 |
|
660 if ($update || $debugUpdate) |
|
661 { |
|
662 foreach my $SOURCE_FILE (sort keys %ActionableFilenamePolicyWarnings) |
|
663 { |
|
664 if (!(open SOURCE_FILE, "< $SOURCE_FILE")) |
|
665 { |
|
666 print ("ERROR: Could not open $SOURCE_FILE to read.\n"); |
|
667 next; |
|
668 } |
|
669 |
|
670 print ("Updating \'$SOURCE_FILE\'...\n") unless ($debugUpdate); |
|
671 |
|
672 my $lineNumbersHashRef = $ActionableFilenamePolicyWarnings{$SOURCE_FILE}; |
|
673 my $lineNumber = 0; |
|
674 my @newSourceFile; |
|
675 |
|
676 while (my $line = <SOURCE_FILE>) |
|
677 { |
|
678 $lineNumber++; |
|
679 |
|
680 if ($lineNumbersHashRef->{$lineNumber}) |
|
681 { |
|
682 print ("\tOriginal : $line") if ($verbose); |
|
683 |
|
684 my $problematicTextHashRef = $lineNumbersHashRef->{$lineNumber}; |
|
685 |
|
686 # We need to order the updates on a per-line basis so that, for example, |
|
687 # a search and update for 'nkern\arm\' occurs after one for 'include\nkern\arm\nk_plat.h' |
|
688 # We can do this by length, making sure the longest updates are performed first |
|
689 my @problematicTextOrderedHashKeys = sort {length $b <=> length $a} (keys %{$problematicTextHashRef}); |
|
690 |
|
691 foreach my $problematicText (@problematicTextOrderedHashKeys) |
|
692 { |
|
693 my $attributesHashRef = $problematicTextHashRef->{$problematicText}; |
|
694 my $revisedText = $problematicText; |
|
695 |
|
696 # Physical |
|
697 |
|
698 if ($attributesHashRef->{PHYSICAL}) |
|
699 { |
|
700 my $physicalRealityHashRef = $attributesHashRef->{PHYSICAL_REALITY}; |
|
701 |
|
702 my $physicalReality = (keys %{$physicalRealityHashRef})[0]; |
|
703 my $physicalRealityUnixSlash = $physicalReality; |
|
704 $physicalRealityUnixSlash =~ s/\\/\//g; |
|
705 |
|
706 if ($physicalReality =~ /($attributesHashRef->{SEARCH_TEXT})$/i || |
|
707 $physicalRealityUnixSlash =~ /($attributesHashRef->{SEARCH_TEXT})$/i) |
|
708 { |
|
709 # Simple case - direct match with just case and slash differences |
|
710 my $replacement = $1; |
|
711 $replacement =~ s/\\/\//g; |
|
712 $revisedText =~ s/$attributesHashRef->{SEARCH_TEXT}/$replacement/; |
|
713 } |
|
714 else |
|
715 { |
|
716 # What we're looking at in the source file doesn't map directly |
|
717 # to what's physically on the file system. |
|
718 |
|
719 my $modifiedSearchText = $problematicText; |
|
720 $modifiedSearchText =~ s/\.\.[\\|\/]//g; |
|
721 $modifiedSearchText =~ s/\.[\\|\/]//g; |
|
722 |
|
723 my $physicalMatchCheck; |
|
724 if ($attributesHashRef->{ACTUAL_TEST}) |
|
725 { |
|
726 $physicalMatchCheck = $attributesHashRef->{ACTUAL_TEST}; |
|
727 } |
|
728 else |
|
729 { |
|
730 $physicalMatchCheck = $modifiedSearchText; |
|
731 } |
|
732 |
|
733 # The physical match check needs to remove double-slashing... |
|
734 $physicalMatchCheck =~ s/\\\\/\\/g; |
|
735 $physicalMatchCheck =~ s/\/\//\//g; |
|
736 |
|
737 $modifiedSearchText = quotemeta($modifiedSearchText); |
|
738 $physicalMatchCheck = quotemeta($physicalMatchCheck); |
|
739 |
|
740 $physicalMatchCheck =~ s/\\\*/\\w\+/g; # * -> \w+ |
|
741 $physicalMatchCheck =~ s/\\\?/\\w\{1\}/g; # ? -> \w{1} |
|
742 |
|
743 if ($physicalReality =~ /($physicalMatchCheck)$/i || |
|
744 $physicalRealityUnixSlash =~ /($physicalMatchCheck)$/i ) |
|
745 { |
|
746 my $replacement = $1; |
|
747 $replacement =~ s/\\/\//g; |
|
748 |
|
749 if ($attributesHashRef->{ACTUAL_TEST} && |
|
750 ($attributesHashRef->{ITEM} =~ /MMP$/ || $attributesHashRef->{ITEM} =~ /DEFFILE/)) |
|
751 { |
|
752 # Both DEFFILE and PRJ_[TEST]MMPFILE entries may be specifed without extension |
|
753 $replacement =~ s/\.\w+$// if ($problematicText !~ /\.\w+$/); |
|
754 |
|
755 # DEFFILE entries may have eabi\bwins in the physical match and had a "u" inserted or appended |
|
756 if ($attributesHashRef->{ITEM} =~ /DEFFILE/ && $replacement !~ /$modifiedSearchText$/i) |
|
757 { |
|
758 $replacement =~ s/(eabi|bwins)\//~\//i if ($problematicText =~ /~[\\|\/]/); |
|
759 $replacement =~ s/u(\.\w+)?$/$1/i if ($attributesHashRef->{ITEM} !~ /NOSTRICTDEF/); |
|
760 } |
|
761 } |
|
762 |
|
763 $revisedText =~ s/$modifiedSearchText/$replacement/; |
|
764 } |
|
765 else |
|
766 { |
|
767 print ("ERROR: Can\'t perform physical consistency updates for:"); |
|
768 |
|
769 my $originalWarningsHashRef = $attributesHashRef->{ORIGINAL_WARNINGS}; |
|
770 foreach my $originalWarning (keys %{$originalWarningsHashRef}) |
|
771 { |
|
772 print ("\t$originalWarning") if ($originalWarning =~ /case versus/); |
|
773 } |
|
774 |
|
775 print ("\n"); |
|
776 } |
|
777 } |
|
778 } |
|
779 |
|
780 # Exclusion |
|
781 |
|
782 if ($attributesHashRef->{EXCLUSION}) |
|
783 { |
|
784 my $exclusionListingSearch = quotemeta($attributesHashRef->{EXCLUSION_LISTING}); |
|
785 $revisedText =~ s/$exclusionListingSearch/$attributesHashRef->{EXCLUSION_LISTING}/i; |
|
786 } |
|
787 |
|
788 # Slash |
|
789 if ($attributesHashRef->{UNIX_SLASH}) |
|
790 { |
|
791 $revisedText =~ s/\\/\//g; |
|
792 $revisedText =~ s/\/\//\//g; # Don't allow replacements that lead to "//" in paths |
|
793 } |
|
794 |
|
795 # Lowercase |
|
796 |
|
797 if ($attributesHashRef->{LOWERCASE}) |
|
798 { |
|
799 $revisedText = lc ($revisedText); |
|
800 } |
|
801 |
|
802 # Default Export |
|
803 |
|
804 if ($attributesHashRef->{DEFAULT_EXPORT}) |
|
805 { |
|
806 my $exportedFilename = lc (basename ($problematicText)); |
|
807 $revisedText .= " \/epoc32\/include\/".$exportedFilename; |
|
808 } |
|
809 |
|
810 $line =~ s/(\"|\<|^|\s){1}$attributesHashRef->{SEARCH_TEXT}/$1$revisedText/; |
|
811 } |
|
812 |
|
813 print ("\tUpdated : $line") if ($verbose); |
|
814 } |
|
815 |
|
816 push @newSourceFile, $line; |
|
817 } |
|
818 |
|
819 close SOURCE_FILE; |
|
820 |
|
821 if ($debugUpdate) |
|
822 { |
|
823 # Don't touch the original source, but create two trees for easy comparison |
|
824 |
|
825 my $baseDir = dirname ($SOURCE_FILE); |
|
826 mkpath ("\\compare\\orig".$baseDir); |
|
827 mkpath ("\\compare\\updated".$baseDir); |
|
828 print ("Copying \'\\compare\\orig".$SOURCE_FILE."\'...\n"); |
|
829 copy ($SOURCE_FILE, "\\compare\\orig".$SOURCE_FILE); |
|
830 $SOURCE_FILE = "\\compare\\updated".$SOURCE_FILE; |
|
831 print ("Updating \'$SOURCE_FILE\'...\n"); |
|
832 } |
|
833 |
|
834 if (!(open SOURCE_FILE, "> $SOURCE_FILE")) |
|
835 { |
|
836 print ("ERROR: Could not open $SOURCE_FILE to write.\n"); |
|
837 next; |
|
838 } |
|
839 |
|
840 foreach my $line (@newSourceFile) |
|
841 { |
|
842 print (SOURCE_FILE $line); |
|
843 } |
|
844 |
|
845 close SOURCE_FILE; |
|
846 } |
|
847 |
|
848 print ("\n") if ($verbose); |
|
849 } |
|
850 |
|
851 __END__ |
|
852 |
|
853 :endofperl |