bldsystemtools/commonbldutils/SFUpdateLicenceHeader.pl
changeset 0 83f4b4db085c
child 2 99082257a271
equal deleted inserted replaced
-1:000000000000 0:83f4b4db085c
       
     1 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # This component and the accompanying materials are made available
       
     3 # under the terms of the License "Eclipse Public License v1.0"
       
     4 # which accompanies this distribution, and is available
       
     5 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     6 #
       
     7 # Initial Contributors:
       
     8 # Nokia Corporation - initial contribution
       
     9 #
       
    10 # Contributors
       
    11 #
       
    12 # Description: Replace S60 header with Symbian Foundation license header.
       
    13 #              Output file (results) is compatibe for SFMakeLxrLinks.pl as input.
       
    14 #
       
    15 use strict;
       
    16 use File::Find;
       
    17 use File::Basename;
       
    18 use Getopt::Long;
       
    19 use IO::Handle;
       
    20 use FindBin qw($Bin);
       
    21 use FileHandle;
       
    22 
       
    23 ####################
       
    24 # Constants
       
    25 ####################
       
    26 
       
    27 # Tool version
       
    28 use constant VERSION => '2.1';
       
    29 # Version history: 0.8 Added copyright year pick-up
       
    30 # Version history: 0.9- Bug fixesg
       
    31 # Version history: 0.95- EPL header support added
       
    32 # Version history: 0.96 Minor script adjustments
       
    33 # Version history: 0.97 Assembly files (.s, .cia, .asm) checked as well
       
    34 # Version history: 0.98 Support for -oem added. Also @file tag removed from template
       
    35 # Version history: 0.99 Testing -oem option
       
    36 # Version history: 1.0 Comment column added for PostProcess script
       
    37 # Version history: 1.01 Modify option bug fixed
       
    38 # Version history: 1.1 Description bug fixed
       
    39 # Version history: 1.2 Digia copyrights moved to SF as well. Also R/O attribute removed only for files modified
       
    40 # Version history: 1.3 Distribution policy files handled as well. With -create also created
       
    41 # Version history: 1.31 Fixes to distribution file handling (only non-empty directories acknowledged)
       
    42 # Version history: 1.32 .pm files checked as well
       
    43 # Version history: 1.4 Bug fixes and "ignorefile" agrument added
       
    44 # Version history: 1.41 Bug fix in Description pick-up
       
    45 # Version history: 1.42 Bug fix in -ignore option (also missing .s60 file creation need to be ignored). Default value set to ignore option
       
    46 # Version history: 1.43 Description statistics fixed, .hpp added, description pick-up improved
       
    47 # Version history: 1.5 -verify option implemented, ignorefile default value extended, statistics go to log
       
    48 # Version history: 1.51 Copyright year pick-up bug fixed, ignorefilepattern comparison case-insensitive
       
    49 # Version history: 1.52 current s60 dumped to result
       
    50 # Version history: 1.53 abld.bat added ti ignorefile default
       
    51 # Version history: 1.54 -verify statistics improved
       
    52 # Version history: 1.55 -eula option added
       
    53 # Version history: 1.56 .mmh files added, extra Non-Nokia check added for "No Copyright" case for weired headers
       
    54 # Version history: 1.57 Changes to -verify
       
    55 # Version history: 1.58 @echo on ... @echo off added to .cmd and .bat headers
       
    56 # Version history: 1.59 EPL warning log entry --> info
       
    57 # Version history: 1.60 and 1.61 -ignorelist option added
       
    58 # Version history: 1.62 Uppercase REM text allowed
       
    59 # Version history: 1.63 Internal directory check added to -verify
       
    60 # Version history: 1.64 Symbian --> Symbian.*Ltd in $ExternalToNokiaCopyrPattern
       
    61 # Version history: 1.65 Bug fixed in normalizeCppComment
       
    62 # Version history: 1.70 Changes to better cope with ex-Symbian sources,
       
    63 #                       Pasi's better "@rem" taken into use for .bat and .cmd files
       
    64 # Version history: 1.71 Config file support added (option -config) for non 3/7 IDs
       
    65 # Version history: 1.72 handleVerify checks improved to include also file start
       
    66 # Version history: 1.73 \b added to Copyright word to reduce if "wrong" alarms
       
    67 # Version history: 1.74 incomplete copyright check added to -verify
       
    68 # Version history: 1.75 Support for ignoring generated headers (@sfGeneratedPatternArray) added
       
    69 # Version history: 1.76 .script extension added (using Cpp comments e.g. // Text)
       
    70 # Version history: 1.77 Reporting and logging improvements for wk19 checks (need to check / patch single files)
       
    71 # Version history: 1.80 Few Qt specific file extensions added, -lgpl option added, 
       
    72 #                       C++ comment fix in handleOem
       
    73 # Version history: 1.90 checkNoMultipleLicenses function added, and call to handleVerify* added
       
    74 # Version history: 2.0 handleDistributionValue() changes IDs 0-->3/7 and 3-->7, 
       
    75 #                      isGeneratedHeader() checks for file content added.
       
    76 # Version history: 2.01 checkPortionsCopyright implemented and applied
       
    77 # Version history: 2.02 Extra license word taken out from EPL header
       
    78 # Version history: 2.1 -verify -epl support added and switchLicense() tried first for SFL --> EPL switching
       
    79 
       
    80 my $IGNORE_MAN ='Ignore-manually';
       
    81 my $IGNORE ='Ignore';
       
    82 my $INTERNAL = 'internal';
       
    83 use constant KEEP_SYMBIAN => 0;
       
    84 use constant REMOVE_SYMBIAN => 1;
       
    85 
       
    86 
       
    87 #file extention list that headers should be replace
       
    88 my @extlist = ('.cpp', '.c', '.h', '.mmp', '.mmpi', '.rss', '.hrh', '.inl', '.inf', '.iby', '.oby',
       
    89             '.loc', '.rh', '.ra', '.java', '.mk', '.bat', '.cmd', '.pkg', '.rls', '.rssi', '.pan', '.py', '.pl', '.s', '.asm', '.cia',
       
    90             '.s60', '.pm', '.hpp', '.mmh', '.script', 
       
    91             '.pro', '.pri');  # Qt specific
       
    92 
       
    93 # Various header comment styles
       
    94 my @header_regexps = 
       
    95 (
       
    96 '^\s*(\#.*?\n)*',           # Perl, Python
       
    97 '^\s*(\@echo\s*off\s*\n)?\n*(@?(?i)rem.*?\n)*(\@echo\s*on\s*)?', # Windows command script
       
    98 '^\s*(\;.*?\n)*',           # SIS package file
       
    99 '\s*\/\*[\n\s\*-=].*?\*\/',  # C comment block
       
   100 '(\s*\/\/.*\n)+',           # C++ comment block  (do not use /s in regexp evaluation !!!)
       
   101 '^\s*((\/\/|\#).*?\n)*'       # Script file comment
       
   102 );
       
   103 
       
   104 # Comment regular expression (Indeces within @header_regexps)
       
   105 use constant COMMENT_PERL => 0;
       
   106 use constant COMMENT_CMD => 1;
       
   107 use constant COMMENT_SIS_ASM => 2;
       
   108 use constant COMMENT_C => 3;
       
   109 use constant COMMENT_CPP => 4;
       
   110 use constant COMMENT_SCRIPT => 5;
       
   111 
       
   112 my $descrTemplateOnly = '\?Description';
       
   113 my $linenumtext = "1";  # Use this linenumer in LXR links
       
   114 
       
   115 # Copyright patterns
       
   116 my $copyrYearPattern = 'Copyright\b.*\d{4}\s*([,-]\s*\d{4})*';
       
   117 my $copyrYearPattern2 = '\d{4}(\s*[,-]\s*\d{4})*';
       
   118 use constant DEFCOPYRIGHTYEAR => "2009";  # For error cases
       
   119 
       
   120 my $NokiaCopyrPattern = '\bCopyright\b.*Nokia.*(All Rights)?';
       
   121 my $NonNokiaCopyrPattern = '\bCopyright\b.*(?!Nokia).*(All Rights)?';
       
   122 my $CopyrPattern = '\bCopyright\b';
       
   123 my $RemoveS60TextBlockPattern = 'This material.*Nokia';
       
   124 my $CC = 'CCHAR';
       
   125 my $BeginLicenseBlockPattern = 'BEGIN LICENSE BLOCK';
       
   126 my $OldNokiaPattern = 'Nokia\s*Corporation[\.\s]*\n';
       
   127 my $NewNokiaText =  "Nokia Corporation and/or its subsidiary(-ies).\n";  # Used in substitu to text
       
   128 my $NewNokiaPattern = "Nokia Corporation and/or its subsidiary";
       
   129 my $OldNokiaPattern2 =  "This material.*including documentation and any related.*protected by copyright controlled.*Nokia";
       
   130 my $PortionsNokiaCopyrPattern = 'Portions.*Copyright\b.*Nokia.*(All Rights)?';
       
   131 my $NewPortionsNokiaCopyrPattern = 'Portions\s*Copyright\b.*' . $NewNokiaPattern;
       
   132 
       
   133 # Move these copyrights to Nokia !!!
       
   134 my $ExternalToNokiaCopyrPattern = 'Copyright\b.*(Symbian\sLtd|Symbian\s*Software\s*Ltd|Digia|SysopenDigia).*(All\s+Rights|All\s+rights)?';
       
   135 my $PortionsSymbianCopyrPattern = 'Portions\s*Copyright\b.*(Symbian\sLtd|Symbian\s*Software\s*Ltd).*(All\s+Rights|All\s+rights)?';
       
   136 
       
   137 ###############
       
   138 # SFL headers
       
   139 ###############
       
   140 # SFL C/C++ style
       
   141 #
       
   142 my $SFLicenseHeader = 
       
   143 '/*
       
   144 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
   145 * All rights reserved.
       
   146 * This component and the accompanying materials are made available
       
   147 * under the terms of the License "Symbi'.'an Foundation License v1.0"
       
   148 * which accompanies this distribution, and is available
       
   149 * at the URL "http://www.symbi'.'anfoundation.org/legal/sf'.'l-v10.html".
       
   150 *
       
   151 * Initial Contributors:
       
   152 * Nokia Corporation - initial contribution.
       
   153 *
       
   154 * Contributors:
       
   155 *
       
   156 * Description:
       
   157 *
       
   158 */'. "\n";
       
   159 
       
   160 # Test string to test header have been changed
       
   161 my $SFLHeaderTest = 'Symbian\s*Foundation\s*License.*www\.symbianfoundation\.org\/legal\/sfl';
       
   162 
       
   163 # Partial SFL  header template (# will be replaced by actual comment syntax char)
       
   164 # Prepare for cases where someone adds spaces to string. 
       
   165 my $SFLicenseHeaderPartial_template = 
       
   166 $CC . '\s*This\s*component\s*and\s*the\s*accompanying\s*materials\s*are\s*made\s*available\s*\n' .
       
   167 $CC . '\s*under\s*the\s*terms\s*of\s*the\s*License\s*\"Symbian\s*Foundation\s*License\s*v1\.0\"\s*\n' .
       
   168 $CC . '\s*which\s*accompanies\s*this\s*distribution\,\s*and\s*is\s*available\s*\n' .
       
   169 $CC . '\s*at\s*the\s*URL\s*\"http\:\/\/www\.symbianfoundation\.org\/legal\/sfl\-v10\.html\"\s*\.';
       
   170  
       
   171 # SFL other comment styles (replace # with actual comment starter)
       
   172 #
       
   173 my $SFLicenseHeader_other_template = 
       
   174 '#
       
   175 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
   176 # All rights reserved.
       
   177 # This component and the accompanying materials are made available
       
   178 # under the terms of the License "Symbi'.'an Foundation License v1.0"
       
   179 # which accompanies this distribution, and is available
       
   180 # at the URL "http://www.symbi','anfoundation.org/legal/sf'.'l-v10.html".
       
   181 #
       
   182 # Initial Contributors:
       
   183 # Nokia Corporation - initial contribution.
       
   184 #
       
   185 # Contributors:
       
   186 #
       
   187 # Description:
       
   188 #
       
   189 ';
       
   190 
       
   191 
       
   192 
       
   193 ###############
       
   194 # EPL headers
       
   195 ###############
       
   196 # C/C++ style
       
   197 my $EPLLicenseHeader = 
       
   198 '/*
       
   199 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
   200 * All rights reserved.
       
   201 * This component and the accompanying materials are made available
       
   202 * under the terms of "Eclipse Public License v1.0"
       
   203 * which accompanies this distribution, and is available
       
   204 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
   205 *
       
   206 * Initial Contributors:
       
   207 * Nokia Corporation - initial contribution.
       
   208 *
       
   209 * Contributors:
       
   210 *
       
   211 * Description: 
       
   212 *
       
   213 */' . "\n";
       
   214 
       
   215 # Test string to test header have been changed
       
   216 my $EPLHeaderTest = 'Eclipse\s*Public\s*License.*www\.eclipse\.org\/legal\/epl';
       
   217 
       
   218 # Partial EPL header  (replace # with actual comment starter)
       
   219 # Prepare for cases where someone adds spaces to string. 
       
   220 my $EPLLicenseHeaderPartial_template = 
       
   221 $CC . '\s*This\s*component\s*and\s*the\s*accompanying\s*materials\s*are\s*made\s*available\s*\n' .
       
   222 $CC . '\s*under\s*the\s*terms\s*of\s*\"Eclipse\s*Public\s*License\s*v1\.0\"\s*\n' .
       
   223 $CC . '\s*which\s*accompanies\s*this\s*distribution,\s*and\s*is\s*available\s*\n' .
       
   224 $CC . '\s*at\s*the\s*URL\s*\"http\:\/\/www\.eclipse\.org\/legal\/epl\-v10\.html\"\s*\.';
       
   225 
       
   226 
       
   227 # EPL other comment styles (replace # with comment starter)
       
   228 #
       
   229 my $EPLLicenseHeader_other_template = 
       
   230 '#
       
   231 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
   232 # All rights reserved.
       
   233 # This component and the accompanying materials are made available
       
   234 # under the terms of "Eclipse Public License v1.0"
       
   235 # which accompanies this distribution, and is available
       
   236 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
   237 #
       
   238 # Initial Contributors:
       
   239 # Nokia Corporation - initial contribution.
       
   240 #
       
   241 # Contributors:
       
   242 #
       
   243 # Description: 
       
   244 #
       
   245 ';
       
   246 
       
   247 ##############
       
   248 # LGPL headers
       
   249 ##############
       
   250 my $LGPLLicenseHeader = 
       
   251 '/*
       
   252 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
   253 * All rights reserved.
       
   254 *
       
   255 * This program is free software: you can redistribute it and/or modify
       
   256 * it under the terms of the GNU Lesser General Public License as published by
       
   257 * the Free Software Foundation, version 2.1 of the License.
       
   258 * 
       
   259 * This program is distributed in the hope that it will be useful,
       
   260 * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
   261 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
   262 * GNU Lesser General Public License for more details.
       
   263 *
       
   264 * You should have received a copy of the GNU Lesser General Public License
       
   265 * along with this program.  If not, 
       
   266 * see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
   267 *
       
   268 * Description:
       
   269 *
       
   270 */';
       
   271 
       
   272 # Test string to test header have been changed
       
   273 my $LGPLHeaderTest = 'GNU\s*Lesser\s*General\s*Public\s*License.*www\.gnu\.org\/licenses/old-licenses\/lgpl-2\.1\.html';
       
   274 
       
   275 # Partial LGPL header  (replace $CC with actual comment starter)
       
   276 my $LGPLLicenseHeaderPartial_template = 
       
   277 $CC . '\s*This\s*program\s*is\s*free\s*software\:\s*you\s*can\s*redistribute\s*it\s*and\/or\s*modify\n' .
       
   278 $CC . '\s*it\s*under\s*the\s*terms\s*of\s*the\s*GNU\s*Lesser\s*General\s*Public\s*License\s*as\s*published\s*by\n' .
       
   279 $CC . '\s*the\s*Free\s*Software\s*Foundation\,\s*version\s*2\.1\s*of\s*the\s*License\n';
       
   280 
       
   281 
       
   282 # LGPL other comment styles (replace # with comment starter)
       
   283 #
       
   284 my $LGPLLicenseHeader_other_template = 
       
   285 '#
       
   286 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
   287 # All rights reserved.
       
   288 #
       
   289 # This program is free software: you can redistribute it and/or modify
       
   290 # it under the terms of the GNU Lesser General Public License as published by
       
   291 # the Free Software Foundation, version 2.1 of the License.
       
   292 # 
       
   293 # This program is distributed in the hope that it will be useful,
       
   294 # but WITHOUT ANY WARRANTY; without even the implied warranty of
       
   295 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
   296 # GNU Lesser General Public License for more details.
       
   297 #
       
   298 # You should have received a copy of the GNU Lesser General Public License
       
   299 # along with this program.  If not, 
       
   300 # see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/".
       
   301 #
       
   302 # Description:
       
   303 #
       
   304 ';
       
   305 
       
   306 
       
   307 ###############
       
   308 # S60 headers
       
   309 ###############
       
   310 # C/C++ style
       
   311 my $S60HeaderPartial_template = 
       
   312 $CC . " This material, including documentation and any related computer\n" .
       
   313 $CC . " programs, is protected by copyright controlled by Nokia. All\n" .
       
   314 $CC . " rights are reserved. Copying, including reproducing, storing\n" .
       
   315 $CC . " adapting or translating, any or all of this material requires the\n" .
       
   316 $CC . " prior written consent of Nokia. This material also contains\n" .
       
   317 $CC . " confidential information which may not be disclosed to others\n" .
       
   318 $CC . " without the prior written consent of Nokia.";
       
   319 
       
   320 # Test string to test header have been changed
       
   321 my $S60HeaderTest = 'is\s*protected\s*by\s*copyright\s*controlled\s*by\s*Nokia';
       
   322 
       
   323 
       
   324 my @SflHeaders = (\$SFLicenseHeader, \$SFLicenseHeader_other_template, \$SFLicenseHeaderPartial_template, \$SFLHeaderTest);   # contains refs
       
   325 my @EplHeaders = (\$EPLLicenseHeader, \$EPLLicenseHeader_other_template, \$EPLLicenseHeaderPartial_template, \$EPLHeaderTest); # contains refs
       
   326 my @S60Headers = (undef,undef,\$S60HeaderPartial_template, \$S60HeaderTest); # contains refs
       
   327 my @LgplHeaders = (\$LGPLLicenseHeader, \$LGPLLicenseHeader_other_template, \$LGPLLicenseHeaderPartial_template, \$LGPLHeaderTest); # contains refs
       
   328 
       
   329 # Header styles (indeces within @SflHeaders and @EplHeaders)
       
   330 use constant CPP_HEADER => 0; 
       
   331 use constant OTHER_HEADER => 1;
       
   332 
       
   333 # switchLicense related values
       
   334 use constant SFL_LICENSE => 3;
       
   335 use constant EPL_LICENSE => 7;
       
   336 use constant S60_LICENSE => 0;
       
   337 use constant LGPL_LICENSE => 4;
       
   338 use constant LICENSE_CHANGED => 1;
       
   339 use constant LICENSE_NONE => 0;
       
   340 use constant LICENSE_ERROR => -1;
       
   341 use constant LICENSE_NOT_SUPPORTED => -2;
       
   342 
       
   343 # Distribution policy file values
       
   344 use constant INTERNAL_DISTRIBUTION_VALUE => "1";
       
   345 use constant ZERO_DISTRIBUTION_VALUE => "0";
       
   346 use constant SFL_DISTRIBUTION_VALUE => "3";  
       
   347 use constant EPL_DISTRIBUTION_VALUE => "7"; # option -epl
       
   348 use constant TSRC_DISTRIBUTION_VALUE => "950"; #
       
   349 use constant NONSF_DISTRIBUTION_VALUE => "Other"; #
       
   350 use constant DISTRIBUTION_FILENAME => "distribution.policy.s60";
       
   351 
       
   352 my $usage = 'SFUpdateLicenHeader.pl tool, version: ' . VERSION .
       
   353 '
       
   354 Usages:
       
   355    perl SFUpdateLicenceHeader.pl [-modify] [-epl] [-oem] [-create]  [-ignorefile pattern]
       
   356         [-output csv-file] [-log logfile] [-verbose level] [-verify] [-append]
       
   357         [-oldoutput old-csv-file]  DIRECTORY|FILE
       
   358 
       
   359    Check switch to SFL header in a directory (and subdirectories under that):
       
   360       perl SFUpdateLicenceHeader.pl -output csv-file -log logfile DIRECTORY
       
   361    Switch to SFL header and modify .policy.s60 files in a directory (and subdirectories under that):
       
   362       perl SFUpdateLicenceHeader.pl -modify -output csv-file -log logfile DIRECTORY
       
   363    Switch to SFL header and modify .policy.s60 files in a single file:
       
   364       perl SFUpdateLicenceHeader.pl -modify -output csv-file -log logfile FILE
       
   365    Switch to EPL header and modify .policy.s60 files:
       
   366       perl SFUpdateLicenceHeader.pl -modify -epl -output csv-file -log logfile DIRECTORY
       
   367    Switch to SFL header and modify/create missing .policy.s60 files:
       
   368       perl SFUpdateLicenceHeader.pl -modify -create -output csv-file -log logfile DIRECTORY
       
   369    Switch to SFL header and ignore files matching CCM file pattern:
       
   370       perl SFUpdateLicenceHeader.pl -modify -ignore "_ccmwaid.inf" -output csv-file -log logfile DIRECTORY
       
   371    Switch to SFL header and ignore files matching  CCM or SVN file patterns:
       
   372       perl SFUpdateLicenceHeader.pl -modify -ignore "(_ccm|.svn)" -output csv-file -log logfile DIRECTORY
       
   373    Switch back to Nokia header (for OEM delivery team):
       
   374       perl SFUpdateLicenceHeader.pl -modify -oem -output csv-file -log logfile DIRECTORY
       
   375    Verify file header changes
       
   376       perl SFUpdateLicenceHeader.pl -verify -output csv-file -log logfile DIRECTORY
       
   377    Verify and append logs and results to single file
       
   378       perl SFUpdateLicenceHeader.pl -verify -append -output AllResults.csv -log AllLogs.log DIRECTORY
       
   379    Verify file header changes and use old result file as add-on configuation (used by -verbose only)
       
   380       perl SFUpdateLicenceHeader.pl -verify -oldoutput old-csv-file -output csv-file -log logfile DIRECTORY
       
   381 
       
   382 For more info, see http://s60wiki.nokia.com/S60Wiki/SFDG-File-Header#SFUpdateLicenceHeader.pl
       
   383 ';
       
   384 
       
   385 # Logging constants
       
   386 use constant LOG_ALWAYS => 0;
       
   387 use constant LOG_INFO => 3;
       
   388 use constant LOG_ERROR => 1;
       
   389 use constant LOG_WARNING => 2;
       
   390 use constant LOG_DEBUG => 4;
       
   391 my @LOGTEXTS = ("", "ERROR: ", "Warning: ", "Info: ", "DEBUG: ");
       
   392 my $sep = ",";
       
   393 my $logFile = "";
       
   394 
       
   395 # Issue categories in result CSV formatted file
       
   396 use constant HEADER_CONTEXT => 'header-issue';
       
   397 use constant DISTRIBUTION_CONTEXT => 'distribution-issue';
       
   398 
       
   399 
       
   400 ####################
       
   401 # Global variables
       
   402 ####################
       
   403 
       
   404 # Command line options
       
   405 my $help = 0;
       
   406 my $outputfile;  
       
   407 my $ignorefilepattern;  # File patterns to ignore
       
   408 # my $optSfl = 1;  # By default sfl is on
       
   409 my $optEpl = 0;  # Use EPL headers
       
   410 my $optLgpl = 0;  # Use LGPL v2.1 headers
       
   411 my $optLogLevel = LOG_INFO;
       
   412 my $optModify = 0;  # (default mode is check)
       
   413 my $optCreate = 0;  # (create missing files)
       
   414 my $optOem = 0;  # OEM delivery to S60 license
       
   415 my $optAppend = 0;  # Append results
       
   416 my $optVerify = 0;  # Verify option
       
   417 my $oldOutputFile;  # Version 1.60 old output file in CSV format
       
   418 my %manualIgnoreFileHash; # Hash of files ignored
       
   419 my $optDescription = 0;  # Output also missing description
       
   420 my $optOutputOK = 0;  # Output also OK issues for -verify 
       
   421 
       
   422 # The last distribution ID
       
   423 my $lastDistributionValue = "";
       
   424 
       
   425 # Config file specific gllobals
       
   426 my $configFile;
       
   427 my $configVersion = "";
       
   428 my @sfDistributionIdArray = ();  # Distribution ID array
       
   429 my @sfGeneratedPatternArray = ();  # Distribution ID array
       
   430 
       
   431 #
       
   432 # Statistics variables
       
   433 #
       
   434 my $fileCount = 0;
       
   435 my $modifiedFileCount = 0;
       
   436 my $willModifiedFileCount = 0;
       
   437 my $noDescrcount = 0;
       
   438 my $otherCopyrCount=0;
       
   439 my $ExternalToNokiaCopyrCount=0;
       
   440 my $NokiaCopyrCount=0;
       
   441 my $NoCopyrCount=0;
       
   442 my $UnclearCopyrCount=0;
       
   443 my $SflToS60Changes = 0;
       
   444 my $EplToS60Changes = 0;
       
   445 my $SflToEplChanges = 0;
       
   446 my $EplToSflChanges = 0;
       
   447 my $LicenseChangeErrors = 0;
       
   448 my $ignoreCount = 0;
       
   449 my $unrecogCount = 0;
       
   450 my $createCount = 0;
       
   451 my @verifyFailedCount = (0,0,0,0,0,0,0,0,0,0,0); 
       
   452 my @verifyFailedCountMsgs = ("Distribution file missing",  # Index 0
       
   453                              "SFL or EPL distribution ID missing",  #1
       
   454                              "SFL or EPL header missing",   #2
       
   455                              "Proper copyright missing",    #3
       
   456                              "Header vs. distribution ID mismatch",   #4
       
   457                              "Internal directory going to SF",         #5
       
   458                              "Old Nokia file header used",         #6
       
   459                              "Unclear Non-Nokia copyright",         #7
       
   460                              "Incomplete copyright",         #8
       
   461                              "OK",     #9
       
   462                              "OK (Non-Nokia)",     #10
       
   463                              "Multiple license"     #11
       
   464                               );
       
   465 use constant VERI_MISSING_FILE => 0;
       
   466 use constant VERI_MISSING_ID => 1;
       
   467 use constant VERI_MISSING_HEADER => 2;
       
   468 use constant VERI_PROPER_COPYRIGHT => 3;
       
   469 use constant VERI_ID_HEADER_MISMATCH => 4;
       
   470 use constant VERI_INTERNAL_TO_SF => 5;
       
   471 use constant VERI_OLD_NOKIA_HEADER => 6;
       
   472 use constant VERI_UNCLEAR_COPYR => 7;
       
   473 use constant VERI_INCOMPLETE_COPYR => 8;
       
   474 use constant VERI_OK => 9;
       
   475 use constant VERI_OK_NON_NOKIA => 10;
       
   476 use constant VERI_MULTIPLE_LICENSES => 11;
       
   477 
       
   478 
       
   479 ##################################
       
   480 # Callback for the find function 
       
   481 # (wanted)
       
   482 # Note ! "no_chdir" not used
       
   483 ##################################
       
   484 sub process_file
       
   485 {
       
   486 
       
   487 	my $full_filename = $File::Find::name; # Full name needed for result and logs !
       
   488     $full_filename =~ s/\\/\//g;  # Standardize name 
       
   489 	my $filename = $_;  # This in filename in the current working directory !
       
   490 
       
   491 	#Skip all directory entries
       
   492 	return if -d;
       
   493 
       
   494     if ($ignorefilepattern && $full_filename =~ m/$ignorefilepattern/i)
       
   495     {
       
   496         printLog(LOG_DEBUG, "File ignored by pattern: ".  $full_filename . "\n");
       
   497         $ignoreCount++;
       
   498         return;
       
   499     }
       
   500 
       
   501     # Set initial value from options, turn off later if needed
       
   502     my $modify = $optModify;
       
   503     my $willmodify = 1; # For statistics only
       
   504 
       
   505 	#skip non-source code files
       
   506 	my ($name, $path, $suffix)=fileparse($_, qr/\.[^.]*/);
       
   507 
       
   508 	my $match = grep {$_ eq lc($suffix)} @extlist;
       
   509     if (!$match)
       
   510     {
       
   511         printLog(LOG_DEBUG, "File ignored: ".  $full_filename . "\n");
       
   512         $ignoreCount++;
       
   513         return;
       
   514     }
       
   515 
       
   516     # As there have been cased where e.g. .pkg file has been saved as Unicode format
       
   517     # Check that we can really modify file (e.g. Unicode files not supported)
       
   518     if (! (-T $filename)) # Text file only !
       
   519     {
       
   520         printLog(LOG_WARNING, "File not in text format: $full_filename\n");
       
   521         return;
       
   522     }
       
   523 
       
   524 
       
   525     printLog(LOG_DEBUG, "Handling ".  $full_filename . "\n");
       
   526 
       
   527 	local($/, *FH);
       
   528     
       
   529     # Open file for reading here, re-open later if modified
       
   530     open(FH, "<$filename") or return printLog(LOG_ERROR, "Failed to open file for reading: $full_filename\n");
       
   531 
       
   532 	my $filecontent = <FH>;  # read whole content into buffer
       
   533     # Standardize the new-line handling in files by replacing \r with \n
       
   534     # Some files may be using  only \r and it causes problems
       
   535     $filecontent =~ s/\r/\n/g;  
       
   536 	
       
   537 	my $modifiedFilecontent;
       
   538 	my $description = "";
       
   539 	my $contributors = "";
       
   540 
       
   541 	#comment mark
       
   542 	my $cm = '\*';
       
   543 	my $cm2 = '*';
       
   544 	my $newheader = "";
       
   545 	my $oldheader = "";
       
   546 	my $oldheader2;
       
   547 	my $header_regexp = "";
       
   548 	my $header_regexp2;
       
   549     my $isCcomment = 0;
       
   550     my $isCPPcomment = 0;
       
   551     my $oldCopyrightYear;
       
   552     my $matchPos1;
       
   553     my $matchPos2;
       
   554     my $unrecog=0;
       
   555 
       
   556 
       
   557     # For statisctics....
       
   558 	$fileCount++;
       
   559 
       
   560     ###################
       
   561 	# Prepare regular expressions 
       
   562     # based on file extensions
       
   563     ###################
       
   564 
       
   565 	if (lc($suffix) eq ".s60")
       
   566     {
       
   567         #
       
   568         # Alter exisring distribution policy file 
       
   569         #
       
   570         my $stat = LICENSE_NONE;
       
   571         $stat = &handleDistributionValue(\$filecontent, $full_filename);
       
   572         if ($stat eq LICENSE_CHANGED)
       
   573         {
       
   574             $willModifiedFileCount++;
       
   575             if ($modify)
       
   576             {
       
   577                close(FH); # Close null 
       
   578                writeFile(\$filecontent, $filename, $full_filename);
       
   579             }
       
   580         }
       
   581         return; # All done
       
   582     }
       
   583     
       
   584 	elsif ( (lc($suffix) eq ".mk" ) or 
       
   585           (lc($suffix) eq ".pl") or (lc($suffix) eq ".py") or (lc($suffix) eq ".pm") or # script
       
   586           (lc($suffix) eq ".pro") or (lc($suffix) eq ".pri") )   # Qt specific
       
   587     {
       
   588         # Makefile, Perl or Python script  (# comment)
       
   589 		$cm = '#';
       
   590 		$cm2 = '#';
       
   591 		$newheader = &headerOf(OTHER_HEADER());
       
   592 		$header_regexp = $header_regexps[COMMENT_PERL];
       
   593     }
       
   594 	elsif ((lc($suffix) eq ".bat" ) or (lc($suffix) eq ".cmd" )) 
       
   595     {
       
   596         # Windows command script (@rem comment)
       
   597 		$cm = '@rem';
       
   598 		$cm2 = '@rem';
       
   599 		$newheader = &headerOf(OTHER_HEADER());
       
   600 		$newheader =~ s/\#/\@rem/g;  # use rem as comment start, not #
       
   601 		#$newheader = "\@echo off\n" . $newheader;  # Disable std output, otherwise rem statements are shown
       
   602 		#$newheader = $newheader . "\@echo on\n"; # Enable std output
       
   603 		$header_regexp = $header_regexps[COMMENT_CMD];
       
   604     }
       
   605 	elsif (lc($suffix) eq ".pkg" or lc($suffix) eq ".asm") 
       
   606     {
       
   607         # SIS package file or Assembly file (; comment)
       
   608 		$cm = ';';
       
   609 		$cm2 = ';';
       
   610 		$newheader = &headerOf(OTHER_HEADER());
       
   611 		$newheader =~ s/\#/\;/g;  # use ; as comment start
       
   612 		$header_regexp = $header_regexps[COMMENT_SIS_ASM];
       
   613 	} 
       
   614 	elsif (lc($suffix) eq ".s") 
       
   615     {
       
   616         # Not all .s files are assemby files !!!
       
   617         #
       
   618         if ($filecontent =~ m/\#include\s*\"armasmdef\.h\"/s)
       
   619         {
       
   620             # ARM assembly file (C comment)
       
   621             $newheader = &headerOf(CPP_HEADER());
       
   622             # Match both C and C++ comment syntaxes
       
   623             $isCcomment = 1;
       
   624             $header_regexp = $header_regexps[COMMENT_C];
       
   625             $header_regexp2 = $header_regexps[COMMENT_CPP];  # Use without /s in regexp eval !
       
   626         }
       
   627         elsif ($filecontent =~ m/[\s\t]+AREA[\s\t]+/s)  # AREA statement
       
   628         {
       
   629             # RVCT assembly file (; comment)
       
   630             $cm = ';';
       
   631             $cm2 = ';';
       
   632             $newheader = &headerOf(OTHER_HEADER());
       
   633             $newheader =~ s/\#/\;/g;  # use ; as comment start
       
   634             $header_regexp = $header_regexps[COMMENT_SIS_ASM];
       
   635         }
       
   636         else
       
   637         {
       
   638             # Not recognized
       
   639             $unrecog = 1;
       
   640             printLog(LOG_WARNING, "Assembly file content not recognized, ignored ".  $full_filename . "\n");
       
   641         }
       
   642 	} 
       
   643 	elsif (lc($suffix) eq ".script" )
       
   644     {
       
   645         # Test scipt (// comment)
       
   646 		$cm = '//';
       
   647 		$cm2 = '//';
       
   648 		$newheader = &headerOf(OTHER_HEADER());
       
   649 		$newheader =~ s/\#/\/\//g;  # use // as comment start
       
   650 		$header_regexp = $header_regexps[COMMENT_SCRIPT];
       
   651     }
       
   652     else
       
   653     {
       
   654         # C/C++ syntaxed file
       
   655 		$newheader = &headerOf(CPP_HEADER());
       
   656         # Match both C and C++ comment syntaxes
       
   657         $isCcomment = 1;
       
   658 	    $header_regexp = $header_regexps[COMMENT_C];
       
   659 	    $header_regexp2 = $header_regexps[COMMENT_CPP];  # Use without /s in regexp eval !
       
   660     }
       
   661 
       
   662     if ($unrecog)
       
   663     {
       
   664         close(FH);
       
   665         $unrecogCount++;
       
   666         return;
       
   667     }
       
   668 
       
   669     ###################
       
   670     # Pick up old header in the very first comment block.
       
   671     # If the actual license text is in the later comment block, it may generate
       
   672     # UNCLEAR COPYRIGHT CASE (See Consistency checks)
       
   673     ###################
       
   674     #
       
   675     if ($header_regexp2)
       
   676     {
       
   677         if ($filecontent =~ m/$header_regexp2/)   # Note /s not used by purpose !
       
   678         {
       
   679             $oldheader = $&;
       
   680             $oldheader2 = $&;
       
   681             $matchPos2 = $-[0];
       
   682             $isCPPcomment = 1;
       
   683             printLog(LOG_DEBUG, "Orig C++ header:$matchPos2=($oldheader)\n");
       
   684         }
       
   685     }
       
   686 
       
   687     if ($filecontent =~ m/$header_regexp/s)
       
   688     {
       
   689         $oldheader = $&;
       
   690         $matchPos1 = $-[0];
       
   691         $isCPPcomment = 0;
       
   692         if ($oldheader2 && ($matchPos2 < $matchPos1)) 
       
   693         {
       
   694             $oldheader = $oldheader2;  # C++ header was earlier
       
   695             $isCPPcomment = 1;  # revert back
       
   696         }
       
   697         else 
       
   698         {
       
   699             printLog(LOG_DEBUG, "Orig C or other header:$header_regexp,$matchPos1\n");
       
   700             printLog(LOG_DEBUG, "Orig C or other header:($oldheader)\n");
       
   701         }
       
   702     }
       
   703 
       
   704     #
       
   705     ###################
       
   706     # Process old header
       
   707     ###################
       
   708 
       
   709     # Handle -verify option
       
   710     if ($optVerify)
       
   711     {
       
   712         if ($optLgpl)
       
   713         {
       
   714             &handleVerifyLgpl(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir);
       
   715         }
       
   716         elsif ($optEpl)
       
   717         {
       
   718             &handleVerifyEpl(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir);
       
   719         }
       
   720         else
       
   721         {
       
   722             &handleVerify(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir);
       
   723         }
       
   724 
       
   725         close(FH);
       
   726         return; # All done
       
   727     }
       
   728 
       
   729     #
       
   730     # Try switch license from SFL to EPL / S60-OEM release
       
   731     #
       
   732     my $switchStat = LICENSE_NONE;
       
   733     $switchStat = &switchLicense(\$filecontent, \$oldheader, $cm, $full_filename, $isCPPcomment);
       
   734     if ($switchStat eq LICENSE_CHANGED)
       
   735     {
       
   736         # OK the switch was sucessful
       
   737         $willModifiedFileCount++;
       
   738         if ($modify)
       
   739         {
       
   740             close(FH);
       
   741             writeFile(\$filecontent, $filename, $full_filename);
       
   742         }
       
   743         close(FH);
       
   744         return;  # All done
       
   745     }
       
   746     elsif ($switchStat eq LICENSE_NOT_SUPPORTED)
       
   747     {
       
   748         close(FH);
       
   749         return;  # No worth continue
       
   750     }
       
   751     
       
   752 
       
   753     # Otherwise (error or no license) continue to create new header
       
   754  
       
   755     ###################
       
   756     # Consistency checks
       
   757     ###################
       
   758     if ( (!($oldheader =~ m/$CopyrPattern/is)) && ($filecontent =~ m/$BeginLicenseBlockPattern/s))
       
   759     {
       
   760         # Looks like header is something weired going on. First comment block contains no copyright, 
       
   761         # and still there is "BEGIN LICENSE" block in the file
       
   762         $UnclearCopyrCount++;
       
   763         printLog(LOG_INFO, "Non-Nokia copyright (#1) ".  $full_filename . "\n");
       
   764         printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright $sep$sep"."BEGIN LICENSE BLOCK$sep$full_filename$sep$linenumtext\n");
       
   765         close(FH);
       
   766         return;
       
   767     }
       
   768 
       
   769     #
       
   770     # Switch license from S60 to SFL/EPL according to options
       
   771     #
       
   772 
       
   773     my $otherCopyr = 0;
       
   774     my $noCopyr = 0;
       
   775     my $ExternalToNokiaCopyr = 0;
       
   776     my $s60header = 0;
       
   777 
       
   778     # First remove all "Nokia copyright" texts + weired "Copyright known-words" from header
       
   779     # This because, the header can contain both Nokia and other company copyright statements
       
   780     my $testheader = makeTestHeader(\$oldheader, 0, REMOVE_SYMBIAN);
       
   781     printLog(LOG_DEBUG, "Cleaned header=($testheader)\n");
       
   782 
       
   783     # Now test whether it contain non-Nokia (=Nokia+Symbian) copyright statements
       
   784     # The rule is: If this hits, do not touch the header
       
   785 
       
   786     if ($testheader =~ m/$NonNokiaCopyrPattern/is)
       
   787     {
       
   788         # Some other than Nokia & Symbian copyright exist in header
       
   789         $otherCopyr = 1;
       
   790         $modify = 0;  # !!! Do not modify file !!!
       
   791         $willmodify = 0; 
       
   792         $otherCopyrCount++;
       
   793         my $failReason = "";
       
   794         if (!checkPortionsCopyright(\$oldheader, 0, \$failReason))
       
   795         {
       
   796             printLog(LOG_WARNING, "Non-Nokia copyright (#2) ".  $full_filename . "\n");
       
   797             printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   798         }
       
   799         else
       
   800         {
       
   801             printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   802             printLog(LOG_INFO, "Non-Nokia (portions Nokia) copyright ".  $full_filename . "\n");
       
   803         }
       
   804 
       
   805         close(FH);
       
   806         return;  # Quit
       
   807     }
       
   808 
       
   809     # Test header has Nokia or Symbian copyright statement or it could be some other comment
       
   810     # Check the rest of file
       
   811     my $wholefile = makeTestHeader(\$filecontent, 1, REMOVE_SYMBIAN);  # Check the rest of file
       
   812     if ($wholefile =~ m/$NonNokiaCopyrPattern/is)
       
   813     {
       
   814         # The header might be empty due to weired file header style.
       
   815         # Check the whole file content, it could be non-nokia file?
       
   816         $modify = 0;  # !!! Do not modify file !!!
       
   817         $willmodify = 0; 
       
   818         my $failReason = "";
       
   819         if (!checkPortionsCopyright(\$filecontent, 1, \$failReason))
       
   820         {
       
   821             $UnclearCopyrCount++;
       
   822             printLog(LOG_INFO, "Non-Nokia copyright (#2) ".  $full_filename . "\n");
       
   823             printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$failReason$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   824         }
       
   825         else
       
   826         {
       
   827             printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   828             printLog(LOG_INFO, "Non-Nokia (portions Nokia) copyright ".  $full_filename . "\n");
       
   829         }
       
   830         close(FH);
       
   831         return;  # Quit
       
   832     }
       
   833 
       
   834     # Check if header is already OK.  
       
   835     # This is needed to keep Ex-Symbian C++ comment syntaxes. 
       
   836     # Also, this avoid unncessary changes in headers.
       
   837     # NOTE ! If header need to be converted to a new format the check must return FALSE !!!
       
   838     my $license = licenceIdForOption();
       
   839     if (checkHeader(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir, \$license))
       
   840     {
       
   841         if (!checkNoMultipleLicenses(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir))
       
   842         {
       
   843             printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$full_filename$sep" ."1\n");
       
   844             printLog(LOG_ERROR, "Multiple licenses:".  $full_filename . "\n");
       
   845             close(FH);
       
   846             return; # Failed
       
   847         }
       
   848         else
       
   849         {
       
   850             # Quit here, header OK
       
   851             printLog(LOG_INFO, "Header already OK ($license): $full_filename\n");
       
   852             close(FH);
       
   853             return;  # Quit
       
   854         }
       
   855     }
       
   856 
       
   857     # Check if Ex-Symbian file
       
   858     my $testheader = makeTestHeader(\$oldheader, 0, KEEP_SYMBIAN);
       
   859     if ($testheader =~ m/$ExternalToNokiaCopyrPattern/is)
       
   860     { 
       
   861         # External copyright moved to Nokia
       
   862         my $txt = $1;
       
   863         $txt =~ s/,//;
       
   864         $ExternalToNokiaCopyr = 1;
       
   865         $ExternalToNokiaCopyrCount++;
       
   866         if ($isCPPcomment) 
       
   867         {
       
   868             # Normalize the C++ header syntax back to C comment
       
   869             $modifiedFilecontent = &normalizeCppComment($header_regexp2,$filecontent, \$oldheader);
       
   870             printLog(LOG_DEBUG, "Normalized External header=($oldheader)\n");
       
   871         }
       
   872         if ($testheader =~ /$copyrYearPattern/) 
       
   873         {
       
   874             if ($& =~ /$copyrYearPattern2/)
       
   875             {
       
   876                 $oldCopyrightYear = $&;
       
   877             }
       
   878             printLog(LOG_DEBUG, "Old copyright=($oldCopyrightYear)\n");
       
   879         }
       
   880         printLog(LOG_INFO, "Copyright will be converted to Nokia: $full_filename\n");
       
   881         printResult(HEADER_CONTEXT() . "$sep"."Converted copyright$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   882     }
       
   883 
       
   884     elsif ($oldheader =~ m/$NokiaCopyrPattern/is)
       
   885     {
       
   886         # Consider it to be Nokia copyright
       
   887         $s60header = 1;
       
   888         $NokiaCopyrCount++;
       
   889         printLog(LOG_DEBUG, "Nokia header=($full_filename)\n");
       
   890         if ($isCPPcomment) 
       
   891         {
       
   892             # Normalize the C++ header syntax back to C comment
       
   893             $modifiedFilecontent = &normalizeCppComment($header_regexp2, $filecontent, \$oldheader);
       
   894             printLog(LOG_DEBUG, "Normalized Nokia header=($oldheader)\n");
       
   895         }
       
   896         if ($oldheader =~ /$copyrYearPattern/) 
       
   897         {
       
   898             if ($& =~ /$copyrYearPattern2/)
       
   899             {
       
   900                 $oldCopyrightYear = $&;
       
   901             }
       
   902             printLog(LOG_DEBUG, "Old copyright2=($oldCopyrightYear)\n");
       
   903         }
       
   904     }
       
   905     elsif (! ($testheader =~ m/$CopyrPattern/is) )
       
   906     {
       
   907        # No copyright in the header.
       
   908        $NoCopyrCount++;
       
   909        $noCopyr = 1;
       
   910        # printResult(HEADER_CONTEXT() . "$sep"."No Copyright$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   911     }
       
   912     else 
       
   913     {
       
   914          $UnclearCopyrCount++;
       
   915          $modify = 0;  # !!! Do not modify file !!!
       
   916          $willmodify = 0; 
       
   917          printLog(LOG_ERROR, "UNCLEAR copyright ".  $full_filename . "\n");
       
   918          printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR COPYRIGHT CASE$sep$sep$sep$full_filename$sep$linenumtext\n");
       
   919     }
       
   920 
       
   921 
       
   922 	# Get description from current header 
       
   923     if ($oldheader =~ m/$cm\s*Description\s*\:(.*?)$cm\s*(Version)/s)
       
   924     {
       
   925         # Description followed by Version
       
   926 		$description = $1;
       
   927         printLog(LOG_DEBUG, "Old description followed by version ($description)\n");
       
   928 	} else 
       
   929     {
       
   930         # Description without Version
       
   931 		# ORIG if ($oldheader =~ m/$cm?\s*Description\s*\:(.*?)$cm\s*(\n)/s)
       
   932 		if ($oldheader =~ m/$cm?\s*Description\s*\:(.*?)($cm|$cm\/|\n)\s*\n/s)
       
   933         {
       
   934             $description = $1;
       
   935             printLog(LOG_DEBUG, "Old description not followed by version ($description)\n");
       
   936         }
       
   937 	}
       
   938 
       
   939     if ($isCcomment)
       
   940     {
       
   941         $description =~ s/\/\*.*//;  # Remove possible /*
       
   942         $description =~ s/\*\/.*//;  # Remove possible */
       
   943         $description =~ s/\=//g;  # Remove possible =/
       
   944     }
       
   945 
       
   946      # Get contributors from old header
       
   947 	if ( $oldheader =~ m/$cm\s*Contributors\s*\:(.*?)$cm\s*Description\s*\:/s)
       
   948     {
       
   949 		$contributors = $1;
       
   950         printLog(LOG_DEBUG, "Old contributors ($contributors)\n");
       
   951 	}
       
   952 
       
   953 	# Keep description text
       
   954     if($description)
       
   955     {
       
   956         $newheader =~ s/Description:[ \t]*\n/Description: $description/s;
       
   957     }
       
   958 
       
   959 
       
   960 	#Keep contributor list
       
   961 	if ($contributors)
       
   962     {
       
   963 		$newheader =~ s/$cm[ \t]*Contributors:[ \t]*\n$cm[ \t]*\n/$cm2 Contributors:$contributors/s;
       
   964 	}
       
   965 
       
   966 
       
   967     ###################
       
   968 	# Modify the header
       
   969     ###################
       
   970 	if($oldheader)
       
   971     {
       
   972         {
       
   973             # Update the old  header to new one
       
   974             # Old header may be just a description comment, e.g. in script
       
   975             #
       
   976 		
       
   977             if ($otherCopyr)
       
   978             {
       
   979                 # Other copyright statement, do not touch !
       
   980                 printLog(LOG_DEBUG, "Non-Nokia file not modified: $full_filename\n");
       
   981             }
       
   982             elsif ($noCopyr)
       
   983             {
       
   984 
       
   985                 # No copyright statement
       
   986                 if (!isGeneratedHeader(\$oldheader))
       
   987                 {
       
   988                     # Just add new header
       
   989                     $filecontent = $newheader . $filecontent;
       
   990                     printLog(LOG_INFO, "New header will be added: $full_filename\n");
       
   991                 }
       
   992                 else
       
   993                 {
       
   994                     printLog(LOG_INFO, "Generated file ignored: $full_filename\n");
       
   995                 }
       
   996             }
       
   997             else
       
   998             {
       
   999                 # Replace the old external / S60 header
       
  1000                 my $newHeaderCopyrYear;
       
  1001                 if ($newheader =~ /$copyrYearPattern2/) 
       
  1002                 {
       
  1003                     # This is picked up from newheader template in this script, so should work always !
       
  1004                     $newHeaderCopyrYear = $&;  # Pick up year from new header
       
  1005                     printLog(LOG_DEBUG, "Template header copyright=($newHeaderCopyrYear)\n");
       
  1006                 }
       
  1007                 if (!$newHeaderCopyrYear)
       
  1008                 {
       
  1009                     # Anyway, some weired error happended
       
  1010                     $newHeaderCopyrYear = DEFCOPYRIGHTYEAR;
       
  1011                 }
       
  1012                 
       
  1013                 # Create new copyright years
       
  1014                 if ($oldCopyrightYear && !($oldCopyrightYear =~ /$newHeaderCopyrYear/))
       
  1015                 {
       
  1016                     # Keep the old copyright !!!
       
  1017                     # !!! If adding new copyright year to old header, uncomment the next line !!!
       
  1018                     # $oldCopyrightYear .= ",$newHeaderCopyrYear";
       
  1019                 }
       
  1020                 if (!$oldCopyrightYear)
       
  1021                 {
       
  1022                     # Nothing found
       
  1023                     $oldCopyrightYear = $newHeaderCopyrYear;
       
  1024                 }
       
  1025                 printLog(LOG_DEBUG, "New header copyright:$oldCopyrightYear\n");
       
  1026                 $newheader =~ s/$newHeaderCopyrYear/$oldCopyrightYear/;
       
  1027                 printLog(LOG_DEBUG, "New header:$full_filename,($newheader)\n");
       
  1028                 if ($modifiedFilecontent) 
       
  1029                 {
       
  1030                     $filecontent = $modifiedFilecontent;  # Use the already modified content as basis
       
  1031                 }
       
  1032 
       
  1033                 #
       
  1034                 # SET THE NEW HEADER
       
  1035                 #
       
  1036                 if (!($filecontent =~ s/$header_regexp/$newheader/s))
       
  1037                 {
       
  1038                     printLog(LOG_ERROR, "FAILED to change file header: ".  $full_filename . "\n");
       
  1039                     $LicenseChangeErrors++;
       
  1040                     $modify = 0;  # Can not modify on failure
       
  1041                     $willmodify = 0; 
       
  1042                 }
       
  1043                 else
       
  1044                 {
       
  1045                     printLog(LOG_INFO, "File header will be changed: $full_filename\n");
       
  1046                 }
       
  1047             }
       
  1048         }
       
  1049 	} 
       
  1050     else
       
  1051     {
       
  1052         if (!isGeneratedHeader(\$filecontent))  # Ensure file is not generated
       
  1053         {
       
  1054             # Missing old header, add new header as such
       
  1055             printLog(LOG_INFO, "Missing header will be added: $full_filename\n");
       
  1056             $filecontent = $newheader."\n".$filecontent;
       
  1057         }
       
  1058         else
       
  1059         {   
       
  1060             printLog(LOG_INFO, "Generated file ignored: $full_filename\n");
       
  1061         }
       
  1062 	}
       
  1063 
       
  1064     if ($description =~ m/^\s*$/g || $description =~ m/$descrTemplateOnly/) 
       
  1065     {
       
  1066         $noDescrcount++;
       
  1067         if ($optDescription)
       
  1068         {
       
  1069             printResult(HEADER_CONTEXT() .  "$sep"."Description missing$sep$sep$sep$full_filename$sep$linenumtext\n");
       
  1070         }
       
  1071     }
       
  1072    
       
  1073     close(FH);
       
  1074 
       
  1075 	if ($modify)
       
  1076     {
       
  1077         # Re-open the file for modifications
       
  1078         chmod 0777, $filename if !-w;  # remove first R/O
       
  1079         open(FH, "+<$filename") or return printLog(LOG_ERROR, "Failed to open file for modifying: $full_filename\n");
       
  1080 		print FH $filecontent or printLog(LOG_ERROR, "Failed to modify file: $full_filename\n");
       
  1081 		truncate(FH, tell(FH));
       
  1082         $modifiedFileCount++;
       
  1083         close(FH);
       
  1084 	}
       
  1085 
       
  1086     if ($willmodify)
       
  1087     {
       
  1088         # Only for statistics
       
  1089         $willModifiedFileCount++;
       
  1090     }
       
  1091 
       
  1092 }
       
  1093 
       
  1094 
       
  1095 
       
  1096 ##################################
       
  1097 # Callback for the find function
       
  1098 # (postprocess)
       
  1099 # Note ! "no_chdir" not used
       
  1100 ##################################
       
  1101 sub postprocess
       
  1102 {
       
  1103 	my $dir = $File::Find::dir; 
       
  1104     printLog(LOG_DEBUG, "postprocess $dir\n");
       
  1105 
       
  1106     return if (-e DISTRIBUTION_FILENAME); # Already exists ?
       
  1107 
       
  1108     my $full_filename = $dir . "/" . DISTRIBUTION_FILENAME; # Full name needed for results and log
       
  1109     my $filename = DISTRIBUTION_FILENAME;
       
  1110 
       
  1111     if ($ignorefilepattern && $full_filename =~ m/$ignorefilepattern/i)
       
  1112     {
       
  1113         printLog(LOG_DEBUG, "Missing file ignored by pattern: ".  $full_filename . "\n");
       
  1114         $ignoreCount++;
       
  1115         return;
       
  1116     }
       
  1117 
       
  1118     my $filecontent = "";
       
  1119     my $stat = LICENSE_NONE;
       
  1120     $stat = &handleDistributionValue(\$filecontent, $full_filename);
       
  1121     if ($stat eq LICENSE_CHANGED && $optCreate && isDirectoryNonEmpty('.'))
       
  1122     {
       
  1123         # Create new distribution file to non-empty directory
       
  1124         printResult(DISTRIBUTION_CONTEXT() . "$sep"."New file$sep$sep$sep$full_filename$sep$linenumtext\n");
       
  1125         if ($optModify)
       
  1126         {
       
  1127             # Without  -modify it is possible to see what new files will created
       
  1128             createAndWriteFile(\$filecontent, $filename, $full_filename);
       
  1129         }
       
  1130         $createCount++; # For statistics
       
  1131     }   
       
  1132 
       
  1133 
       
  1134 }
       
  1135 
       
  1136 
       
  1137 ##################################
       
  1138 # Callback for the find function
       
  1139 # (preprocess). Used by option -verify
       
  1140 # Note ! "no_chdir" not used
       
  1141 ##################################
       
  1142 sub preprocess
       
  1143 {
       
  1144 	my $dir = $File::Find::dir; 
       
  1145     printLog(LOG_DEBUG, "preprocess $dir\n");
       
  1146     $lastDistributionValue = "";  # Empty first
       
  1147 
       
  1148     if (!isDirectoryNonEmpty('.'))
       
  1149     {
       
  1150         # Ignore empty dirs
       
  1151         return @_; # Return input args
       
  1152     }
       
  1153     if (!$optVerify)
       
  1154     {
       
  1155         return @_; # Return input args
       
  1156     }
       
  1157 
       
  1158     #
       
  1159     # Currently option -verify  required !!!
       
  1160     #
       
  1161 
       
  1162     my $full_filename = $dir . "/" . DISTRIBUTION_FILENAME; # Full name needed for results and log
       
  1163     $full_filename =~ s/\\/\//g;  # Standardize name 
       
  1164 
       
  1165     my $filename = DISTRIBUTION_FILENAME;
       
  1166     if ($ignorefilepattern && $full_filename =~ m/$ignorefilepattern/i)
       
  1167     {
       
  1168         if (! ($dir =~ m/$INTERNAL/i) )
       
  1169         {
       
  1170             return @_;
       
  1171         }
       
  1172     }
       
  1173 
       
  1174     # Check existency of the file
       
  1175     if (!open(FH, "<$filename"))
       
  1176     {
       
  1177          printResult(DISTRIBUTION_CONTEXT() . "$sep"."Distribution policy file missing$sep$sep$sep$full_filename$sep$linenumtext\n");
       
  1178          $verifyFailedCount[VERI_MISSING_FILE]++;
       
  1179          return @_;   # Return input args
       
  1180     }
       
  1181 
       
  1182 	my $content = <FH>;  # IF CONTENT CHECKS
       
  1183     close FH;
       
  1184 
       
  1185     $content =~ s/\n//g;  # Remove all new-lines
       
  1186     $content =~ s/^\s+//g;  # trim left
       
  1187     $content =~ s/\s+$//g;  # trim right
       
  1188     $lastDistributionValue = $content;  # Save to global variable for the sub handleVerify
       
  1189 
       
  1190     printLog(LOG_DEBUG, "$full_filename content=$content\n");
       
  1191 
       
  1192     if ($dir =~ m/$INTERNAL/i)
       
  1193     {
       
  1194         if ( ($content eq SFL_DISTRIBUTION_VALUE) || ($content eq EPL_DISTRIBUTION_VALUE) )
       
  1195         {
       
  1196             # Internal directory has SFL or EPL distribution value, something is wrong !
       
  1197             my $comment = "";  # Leave it just empty
       
  1198             printResult(DISTRIBUTION_CONTEXT() . "$sep"."Internal directory going to SF (current value $content)$sep$comment$sep$sep$full_filename$sep$linenumtext\n");
       
  1199             $verifyFailedCount[VERI_INTERNAL_TO_SF]++;
       
  1200         }
       
  1201     }
       
  1202     elsif (! (($content eq SFL_DISTRIBUTION_VALUE) || ($content eq EPL_DISTRIBUTION_VALUE)))
       
  1203     {
       
  1204          # Neither SFL nor EPL value
       
  1205          my $comment = getCommentText($content,0,"0,3,7,950", $full_filename);
       
  1206          my $isSFId = &isSFDistribution($content);
       
  1207          if (!$isSFId)
       
  1208          {
       
  1209             printResult(DISTRIBUTION_CONTEXT() . "$sep"."SFL or EPL value missing (current value $content)$sep$comment$sep$sep$full_filename$sep$linenumtext\n");
       
  1210             $verifyFailedCount[VERI_MISSING_ID]++;
       
  1211          }
       
  1212     }
       
  1213 
       
  1214     return @_;   # Return input args
       
  1215 
       
  1216 }
       
  1217 
       
  1218 ##################################################
       
  1219 # Read distribution file from given directory
       
  1220 ##################################################
       
  1221 sub readDistributionValue
       
  1222 {
       
  1223     
       
  1224     my $dir = shift;
       
  1225 
       
  1226     my $filename = DISTRIBUTION_FILENAME;
       
  1227     my $content = "";
       
  1228 
       
  1229     if (open(FH, "<$filename"))
       
  1230     {
       
  1231         $content = <FH>; 
       
  1232         close FH;
       
  1233     }
       
  1234 
       
  1235     $content =~ s/\n//g;  # Remove all new-lines
       
  1236     $content =~ s/^\s+//g;  # trim left
       
  1237     $content =~ s/\s+$//g;  # trim right
       
  1238 
       
  1239     return $content;
       
  1240 }
       
  1241 
       
  1242 
       
  1243 ##################################################
       
  1244 # Make test header from given input text
       
  1245 ##################################################
       
  1246 sub makeTestHeader
       
  1247 {
       
  1248     my $ref = shift;          # Input text reference
       
  1249     my $isWholeFile = shift;  # $ref is the file content
       
  1250     my $removeExternalToNokia = shift; # Remove to Nokia transferreable copyright texts
       
  1251 
       
  1252     my $tstheader = "";
       
  1253 
       
  1254     if (!$isWholeFile)
       
  1255     {
       
  1256         $tstheader = $$ref;
       
  1257     }
       
  1258     else
       
  1259     {
       
  1260         # To optimize, whole file == 10k !!!
       
  1261         # The proper header should be included in that amount of data.
       
  1262         $tstheader = substr($$ref, 0, 10*1024);
       
  1263     }
       
  1264     $tstheader =~ s/$NokiaCopyrPattern//gi;
       
  1265     $tstheader =~ s/$PortionsNokiaCopyrPattern//gi;
       
  1266     $tstheader =~ s/$RemoveS60TextBlockPattern//si;
       
  1267     if ($removeExternalToNokia)
       
  1268     {
       
  1269         $tstheader =~ s/$ExternalToNokiaCopyrPattern//gi;
       
  1270         $tstheader =~ s/$PortionsSymbianCopyrPattern//gi;
       
  1271     }
       
  1272 
       
  1273     # Take out special texts containing copyright word
       
  1274     $tstheader =~ s/Copyright\s*\(c\)\s*\.//gi; 
       
  1275     $tstheader =~ s/COPYRIGHT[\s\n\*\#+;]*(HOLDER|OWNER|notice)//gi;
       
  1276 
       
  1277     return $tstheader;
       
  1278 }
       
  1279 
       
  1280 
       
  1281 ##################################################
       
  1282 # Check whether portions copyright is OK
       
  1283 # Call this for non Nokia cases only !
       
  1284 ##################################################
       
  1285 sub checkPortionsCopyright
       
  1286 {
       
  1287     my $ref = shift;          # Input text reference
       
  1288     my $isWholeFile = shift;  # $ref is the file content
       
  1289     my $failReason_ref = shift;  # check failure reason (OUT)
       
  1290 
       
  1291     my $tstheader = "";
       
  1292 
       
  1293     if (!$isWholeFile)
       
  1294     {
       
  1295         $tstheader = $$ref;
       
  1296     }
       
  1297     else
       
  1298     {
       
  1299         # The portions info should be included within first 10 Kb of file
       
  1300         $tstheader = substr($$ref, 0, 10*1024);  
       
  1301     }
       
  1302 
       
  1303     if ($tstheader =~ m/$PortionsSymbianCopyrPattern/is)
       
  1304     {
       
  1305         # Symbian portions copyright should be converted to Nokia one
       
  1306         if (!($tstheader =~ m/$PortionsNokiaCopyrPattern/is))
       
  1307         {
       
  1308             $$failReason_ref = "(portions Symbian copyright)";
       
  1309         }   
       
  1310         else
       
  1311         {
       
  1312             $$failReason_ref = "(portions Nokia+Symbian copyright)";
       
  1313         }   
       
  1314         return 0;
       
  1315     }
       
  1316 
       
  1317     if (!($tstheader =~ m/$NewPortionsNokiaCopyrPattern/is))
       
  1318     {
       
  1319         # No portions copyright present
       
  1320         $$failReason_ref = "";
       
  1321         return 0;
       
  1322     }
       
  1323 
       
  1324     return 1;  # Should be OK
       
  1325 }
       
  1326 
       
  1327 
       
  1328 ##################################################
       
  1329 # Get comment text by ID or filename
       
  1330 # Returns currently empty or value of the $IGNORE
       
  1331 ##################################################
       
  1332 sub getCommentText
       
  1333 {
       
  1334     my $distributionValue = shift;
       
  1335     my $contains = shift;
       
  1336     my $pattern = shift;
       
  1337     my $fullfilename = shift;
       
  1338 
       
  1339     if ($contains)
       
  1340     {
       
  1341         if ($pattern =~ m/$distributionValue/)
       
  1342         {
       
  1343             return $IGNORE;
       
  1344         }
       
  1345     }
       
  1346     else
       
  1347     {
       
  1348         # Not contains
       
  1349         if (!($pattern =~ m/$distributionValue/))
       
  1350         {
       
  1351             return $IGNORE;
       
  1352         }
       
  1353     }
       
  1354 
       
  1355     my $ignoreThis = $manualIgnoreFileHash{lc($fullfilename)};
       
  1356     if (defined $ignoreThis) 
       
  1357     {
       
  1358         printLog(LOG_DEBUG, "$IGNORE_MAN 2: $fullfilename\n");
       
  1359         return $IGNORE_MAN;
       
  1360     }
       
  1361 
       
  1362     return "";
       
  1363 }
       
  1364 
       
  1365 
       
  1366 ##################################################
       
  1367 # Write content to file
       
  1368 ##################################################
       
  1369 sub writeFile
       
  1370 {
       
  1371     my $filecontent_ref = shift;
       
  1372     my $filename = shift;
       
  1373     my $full_filename = shift;
       
  1374 
       
  1375 	my $fh;
       
  1376 
       
  1377     chmod 0777, $filename if !-w;  # remove first R/O
       
  1378     open($fh, "+<$filename") or return printLog(LOG_ERROR, "Failed to open file for modifying: $full_filename\n");
       
  1379     print $fh $$filecontent_ref or printLog(LOG_ERROR, "Failed to modify file: $full_filename\n");
       
  1380     truncate($fh, tell($fh));
       
  1381     close($fh);
       
  1382 
       
  1383     $modifiedFileCount++;
       
  1384 }
       
  1385 
       
  1386 ##################################################
       
  1387 # Create file and write content to file
       
  1388 ##################################################
       
  1389 sub createAndWriteFile
       
  1390 {
       
  1391     my $filecontent_ref = shift;
       
  1392     my $filename = shift;
       
  1393     my $full_filename = shift;
       
  1394 
       
  1395 	my $fh;
       
  1396 
       
  1397     open($fh, ">$filename") or return printLog(LOG_ERROR, "Failed to create file: $full_filename\n");
       
  1398     print $fh $$filecontent_ref or printLog(LOG_ERROR, "Failed to write  file: $full_filename\n");
       
  1399     close($fh);
       
  1400 }
       
  1401 
       
  1402 ##################################
       
  1403 # Check if current directory is empty
       
  1404 ##################################
       
  1405 sub isDirectoryNonEmpty
       
  1406 {
       
  1407   my ($dir) = @_;
       
  1408   opendir (DIR,$dir) or printLog(LOG_ERROR, "Can't opendir $dir\n");
       
  1409   for(readdir DIR)
       
  1410   {
       
  1411     if (-f $_)
       
  1412     {
       
  1413       closedir DIR;
       
  1414       return 1;
       
  1415     };
       
  1416   }
       
  1417   closedir DIR;
       
  1418   return 0;
       
  1419 }
       
  1420 
       
  1421 
       
  1422 ##################################################
       
  1423 # Change SFL back to S60, or
       
  1424 # Change SFl to EPL
       
  1425 # Returns LICENSE_CHANGED if function switched the license succesfully
       
  1426 ##################################################
       
  1427 # Switch only license text  and URL
       
  1428 my $sflText = '"Symbian Foundation License v1.0"';
       
  1429 my $sflTextPattern = '(the\s*License\s*)?\"Symbian\s*Foundation\s*License\s*v1\.0\"'; 
       
  1430 my $sflUrlPattern = 'http\:\/\/www\.symbianfoundation\.org\/legal\/sfl\-v10\.html';
       
  1431 my $sflUrl = 'http://www.symbianfoundation.org/legal/sf'.'l-v10.html';
       
  1432 my $eplText = '"Eclipse Public License v1.0"';
       
  1433 my $eplUrl = 'http://www.eclipse.org/legal/epl-v10.html';
       
  1434 my $eplUrlPattern = 'http\:\/\/www\.eclipse\.org\/legal\/epl\-v10\.html';
       
  1435 my $eplTextPattern = '"Eclipse\s*Public\s*License\s*v1\.0"';
       
  1436 my $oldEplTextPattern = 'the\s*License\s*"Eclipse\s*Public\s*License\s*v1\.0'; # "the License" is unncessary
       
  1437 
       
  1438 sub switchLicense
       
  1439 {
       
  1440     my $filecontent_ref = shift;
       
  1441     my $header_ref = shift;
       
  1442     my $commentChar = shift;
       
  1443     my $fullfilename = shift;
       
  1444     my $isCPPcomment = shift;
       
  1445 
       
  1446 	my $testValueSfl = "";
       
  1447 	my $testValueEpl = "";
       
  1448 	my $testValueS60 = "";
       
  1449 
       
  1450     if ($isCPPcomment)
       
  1451     {
       
  1452         # xSymbian files use this style
       
  1453         $commentChar = '//';
       
  1454         # in xSymbian files there are comments like, /// some text
       
  1455         $$filecontent_ref =~ s/(\/){3,}/\/\//g;  # replace ///+ back to //
       
  1456     }
       
  1457 
       
  1458 
       
  1459     # In from value \* need to be escaped.
       
  1460     my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl);
       
  1461     my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl);
       
  1462 
       
  1463     $commentChar =~ s/\\//; # Remove \ from  possible  \*
       
  1464     my $ToS60Text = &partialHeaderOf(S60_LICENSE,$commentChar, \$testValueS60);
       
  1465 
       
  1466     # Note that partial headers are manually quoted in the declaration
       
  1467     # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones
       
  1468     # because plain text contains special chars, like .
       
  1469 
       
  1470     printLog(LOG_DEBUG, "switchLicense: $fullfilename, $testValueEpl\n");
       
  1471 
       
  1472     if ($$filecontent_ref =~ m/$testValueSfl/s)
       
  1473     {
       
  1474         # SFL license
       
  1475 
       
  1476         if ($optOem)
       
  1477         {
       
  1478             # Switch from SFL to S60
       
  1479             if (!($$filecontent_ref =~ s/$FromSFLText/$ToS60Text/s))
       
  1480             {
       
  1481                 printLog(LOG_ERROR, "FAILED to change SFL license to S60: ".  $fullfilename . "\n");
       
  1482                 $LicenseChangeErrors++;
       
  1483                 return LICENSE_ERROR;
       
  1484             }
       
  1485             printLog(LOG_WARNING, "License will be swicthed from SFL to S60: ".  $fullfilename . "\n");
       
  1486             $SflToS60Changes++;
       
  1487             return LICENSE_CHANGED;
       
  1488        }
       
  1489        elsif ($optEpl)
       
  1490        {
       
  1491             # Switch from SFL to EPL
       
  1492             if (! ( ($$filecontent_ref =~ s/$sflTextPattern/$eplText/s) && ($$filecontent_ref =~ s/$sflUrlPattern/$eplUrl/s) ) )
       
  1493             {
       
  1494                 printLog(LOG_ERROR, "FAILED to change SFL to EPL: ".  $fullfilename . "\n");
       
  1495                 $LicenseChangeErrors++;
       
  1496                 return LICENSE_ERROR;
       
  1497             }
       
  1498             else
       
  1499             {
       
  1500                 printLog(LOG_INFO, "License will be switched from SFL to EPL: ".  $fullfilename . "\n");
       
  1501             }
       
  1502             $SflToEplChanges++;
       
  1503             return LICENSE_CHANGED;
       
  1504        }
       
  1505     }
       
  1506 
       
  1507     if ($$filecontent_ref =~ m/$testValueEpl/s)
       
  1508     {
       
  1509         if ($optOem)
       
  1510         {
       
  1511              printLog(LOG_ERROR, "Not supported to change EPL to S60: ".  $fullfilename . "\n");
       
  1512              return LICENSE_NOT_SUPPORTED;
       
  1513         }
       
  1514         elsif (!$optEpl)
       
  1515         {
       
  1516             # Switch from EPL  to SFL
       
  1517             if (! ( ($$filecontent_ref =~ s/$eplTextPattern/$sflText/s) && ($$filecontent_ref =~ s/$eplUrlPattern/$sflUrl/s) ) )
       
  1518             {
       
  1519                 printLog(LOG_ERROR, "FAILED to change EPL to SFL: ".  $fullfilename . "\n");
       
  1520                 $LicenseChangeErrors++;
       
  1521                 return LICENSE_ERROR;
       
  1522             }
       
  1523             else
       
  1524             {
       
  1525                 printLog(LOG_WARNING, "License will be switched from EPL to SFL: ".  $fullfilename . "\n");
       
  1526             }
       
  1527             $EplToSflChanges++;
       
  1528             return LICENSE_CHANGED;
       
  1529         }
       
  1530 
       
  1531         # EPL text cleanup (remove unncessary "the License")
       
  1532          if ($$filecontent_ref =~ m/$oldEplTextPattern/s)
       
  1533          {
       
  1534              # EPL header contains extra words, get rid of them (allow script replace old header)
       
  1535              if ($$filecontent_ref =~ s/$oldEplTextPattern/$eplText/s)
       
  1536              {
       
  1537                  # Not error if fails
       
  1538                  printLog(LOG_INFO, "Unnecessary \"the License\" will be removed: $fullfilename\n");
       
  1539                  return LICENSE_CHANGED;
       
  1540              }
       
  1541          }
       
  1542 
       
  1543     }
       
  1544     else
       
  1545     {
       
  1546         return LICENSE_NONE;  # Allow caller decide
       
  1547     }
       
  1548 
       
  1549 }
       
  1550 
       
  1551 ##################################################
       
  1552 # Verify changes
       
  1553 ##################################################
       
  1554 sub handleVerify
       
  1555 {
       
  1556     my $filecontent_ref = shift;
       
  1557     my $header_ref = shift;
       
  1558     my $commentChar = shift;
       
  1559     my $fullfilename = shift;
       
  1560     my $directory = shift;
       
  1561 
       
  1562 	my $testValueSfl = "";
       
  1563 	my $testValueEpl = "";
       
  1564     my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl);
       
  1565     my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl);
       
  1566 
       
  1567     if ($lastDistributionValue eq "")
       
  1568     {
       
  1569         # Distribution file may be empty if giving single file as input
       
  1570         # Read it
       
  1571         $lastDistributionValue = readDistributionValue($directory);
       
  1572     }
       
  1573 
       
  1574     printLog(LOG_DEBUG, "handleVerify $fullfilename, $$header_ref\n");
       
  1575 
       
  1576     # First check Non-Nokia copyright files
       
  1577     my $testheader = makeTestHeader($header_ref, 0, REMOVE_SYMBIAN);
       
  1578     if (($testheader =~ m/$NonNokiaCopyrPattern/is))
       
  1579     {
       
  1580         printLog(LOG_DEBUG, "DEBUG:Extra check1 $&\n");
       
  1581         if (!($testheader =~ m/$ExternalToNokiaCopyrPattern/si))
       
  1582         {
       
  1583             # Non-nokia file
       
  1584             if ($testheader =~ m/$copyrYearPattern/si)
       
  1585             {
       
  1586                 # Looks like copyright statement
       
  1587                 printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1588                 $otherCopyrCount++;
       
  1589                 $verifyFailedCount[VERI_OK_NON_NOKIA]++;
       
  1590                 return 1; # OK
       
  1591             }
       
  1592             else    
       
  1593             {
       
  1594                 # Incomplete copyright ?
       
  1595                 printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia incomplete copyright$sep" . "$IGNORE?$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1596                 $verifyFailedCount[VERI_OK]++;
       
  1597                 return 0;  
       
  1598             }
       
  1599         }
       
  1600     }
       
  1601 
       
  1602     # The header might be empty due to weired file header style.
       
  1603     # Check the whole file content, it could be non-nokia file?
       
  1604     my $filestart = makeTestHeader($filecontent_ref, 1, REMOVE_SYMBIAN);
       
  1605 
       
  1606     if ($filestart =~ m/$NonNokiaCopyrPattern/is)
       
  1607     {
       
  1608         # There is Non-Nokia copyright statement in the file
       
  1609         if (($filestart =~ m/$testValueSfl/is) || ($filestart =~ m/$testValueEpl/is))
       
  1610         {
       
  1611             # Non-Nokia file, but still SFL or EPL header
       
  1612             printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright with SFL/EPL$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1613             $verifyFailedCount[VERI_UNCLEAR_COPYR]++;
       
  1614             return 0;
       
  1615         }
       
  1616         elsif ($$filecontent_ref =~ m/$OldNokiaPattern2/is) 
       
  1617         {
       
  1618             printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Old Nokia copyright$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1619             $verifyFailedCount[VERI_OLD_NOKIA_HEADER]++;
       
  1620             return 0;
       
  1621         }
       
  1622         else
       
  1623         {
       
  1624             # Non-Nokia file
       
  1625             my $failReason = "";
       
  1626             if (!checkPortionsCopyright($filecontent_ref, 1, \$failReason))
       
  1627             {
       
  1628                 printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright$failReason$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1629                 $verifyFailedCount[VERI_UNCLEAR_COPYR]++;
       
  1630                 return 0;
       
  1631             }
       
  1632             else
       
  1633             {
       
  1634                 # Contains portions copyright
       
  1635                 printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1636                 return 1;
       
  1637             }
       
  1638         }
       
  1639     }
       
  1640 
       
  1641     #
       
  1642     # OK, it should be Nokia copyrighted file
       
  1643     #
       
  1644 
       
  1645     # Note that partial headers are manually quoted in the declaration
       
  1646     # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones
       
  1647     # because plain text contains special chars, like .
       
  1648     printLog(LOG_DEBUG, "handleVerify testheaders: $testValueSfl,$testValueEpl,$$header_ref\n");
       
  1649 
       
  1650     if ( !( ($$header_ref =~ m/$testValueSfl/s) || ($$header_ref =~ m/$testValueEpl/s) ||
       
  1651             ($$filecontent_ref =~ m/$testValueSfl/s) || ($$filecontent_ref =~ m/$testValueEpl/s) 
       
  1652        )  )
       
  1653     {
       
  1654         # Header not found from header or whole file
       
  1655        if (isGeneratedHeader($header_ref) || isGeneratedHeader($filecontent_ref))
       
  1656        {
       
  1657             # OK, it is generated header
       
  1658             if ($optOutputOK)
       
  1659             {
       
  1660                 printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "Generated header$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1661             }
       
  1662             $verifyFailedCount[VERI_OK]++;
       
  1663             return 1;  # OK
       
  1664        }
       
  1665 
       
  1666         my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename);
       
  1667         if (($$header_ref =~ m/$OldNokiaPattern2/is) || ($$filecontent_ref =~ m/$OldNokiaPattern2/is))
       
  1668         {
       
  1669             printResult(HEADER_CONTEXT() . "$sep"."SFL or EPL header missing (old Nokia copyright)$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1670         }
       
  1671         else
       
  1672         {
       
  1673             printResult(HEADER_CONTEXT() . "$sep"."SFL or EPL header missing$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1674         }
       
  1675         $verifyFailedCount[VERI_MISSING_HEADER]++;
       
  1676         return 0;
       
  1677     }
       
  1678 
       
  1679     # Cross header versus distribution ID
       
  1680     if ($lastDistributionValue ne "")
       
  1681     {
       
  1682         # Also other than 3 or 7 may be OK based on the config file
       
  1683         my $isSFId = &isSFDistribution($lastDistributionValue);
       
  1684         printLog(LOG_DEBUG, "DEBUG:handleVerify:Other ID OK=$isSFId\n");
       
  1685         if ( (($$header_ref =~ m/$testValueSfl/s) || ($$filecontent_ref =~ m/$testValueSfl/s)) && !$isSFId)
       
  1686         {
       
  1687             my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename);
       
  1688             printResult(HEADER_CONTEXT() . "$sep"."SFL header vs. distribution id ($lastDistributionValue) mismatch$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1689             $verifyFailedCount[VERI_ID_HEADER_MISMATCH]++;
       
  1690             return 0;
       
  1691         }
       
  1692         if ( (($$header_ref =~ m/$testValueEpl/s) || ($$filecontent_ref =~ m/$testValueEpl/s)) && !$isSFId )
       
  1693         {
       
  1694             my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename);
       
  1695             printResult(HEADER_CONTEXT() . "$sep"."EPL header vs. distribution id ($lastDistributionValue) mismatch$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1696             $verifyFailedCount[VERI_ID_HEADER_MISMATCH]++;
       
  1697             return 0;
       
  1698         }
       
  1699     }
       
  1700 
       
  1701     if (!checkNoMultipleLicenses($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory))
       
  1702     {
       
  1703         printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$fullfilename$sep" ."1\n");
       
  1704         printLog(LOG_ERROR, "Multiple licenses:".  $fullfilename . "\n");
       
  1705         $verifyFailedCount[VERI_MULTIPLE_LICENSES]++;
       
  1706         return 0; # Failed
       
  1707     }
       
  1708 
       
  1709 
       
  1710     # We should have proper header in place 
       
  1711 
       
  1712     printLog(LOG_DEBUG, "handleVerify: $$filecontent_ref\n");
       
  1713     # Check New Nokia copyright pattern (added one sentence to the old one)
       
  1714     if (! (($$header_ref =~ m/$NewNokiaPattern/s) || ($$filecontent_ref =~ m/$NewNokiaPattern/s)) )
       
  1715     {
       
  1716         my $comment = getCommentText($lastDistributionValue, 0, "0,3,7,950", $fullfilename);
       
  1717         printResult(HEADER_CONTEXT() . "$sep"."Proper Nokia copyright statement missing$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1718         $verifyFailedCount[VERI_PROPER_COPYRIGHT]++;
       
  1719         return 0; # Failed
       
  1720     }
       
  1721 
       
  1722     if ($optOutputOK)
       
  1723     {
       
  1724         printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "OK$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1725     }
       
  1726     $verifyFailedCount[VERI_OK]++;
       
  1727 
       
  1728     return 1;
       
  1729 
       
  1730 }
       
  1731 
       
  1732 
       
  1733 ##################################################
       
  1734 # Verify changes
       
  1735 ##################################################
       
  1736 sub handleVerifyEpl
       
  1737 {
       
  1738     my $filecontent_ref = shift;
       
  1739     my $header_ref = shift;
       
  1740     my $commentChar = shift;
       
  1741     my $fullfilename = shift;
       
  1742     my $directory = shift;
       
  1743 
       
  1744 	my $testValueSfl = "";
       
  1745 	my $testValueEpl = "";
       
  1746     my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl);
       
  1747     my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl);
       
  1748 
       
  1749     if ($lastDistributionValue eq "")
       
  1750     {
       
  1751         # Distribution file may be empty if giving single file as input
       
  1752         # Read it
       
  1753         $lastDistributionValue = readDistributionValue($directory);
       
  1754     }
       
  1755 
       
  1756     printLog(LOG_DEBUG, "handleVerifyEpl $fullfilename, $$header_ref\n");
       
  1757 
       
  1758     # First check Non-Nokia copyright files
       
  1759     my $testheader = makeTestHeader($header_ref, 0, REMOVE_SYMBIAN);
       
  1760     if (($testheader =~ m/$NonNokiaCopyrPattern/is))
       
  1761     {
       
  1762         printLog(LOG_DEBUG, "DEBUG:Extra check1 $&\n");
       
  1763         if (!($testheader =~ m/$ExternalToNokiaCopyrPattern/si))
       
  1764         {
       
  1765             # Non-nokia file
       
  1766             if ($testheader =~ m/$copyrYearPattern/si)
       
  1767             {
       
  1768                 # Looks like copyright statement
       
  1769                 printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1770                 $otherCopyrCount++;
       
  1771                 $verifyFailedCount[VERI_OK_NON_NOKIA]++;
       
  1772                 return 1; # OK
       
  1773             }
       
  1774             else    
       
  1775             {
       
  1776                 # Incomplete copyright ?
       
  1777                 printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia incomplete copyright$sep" . "$IGNORE?$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1778                 $verifyFailedCount[VERI_OK]++;
       
  1779                 return 0;  
       
  1780             }
       
  1781         }
       
  1782     }
       
  1783 
       
  1784     # The header might be empty due to weired file header style.
       
  1785     # Check the whole file content, it could be non-nokia file?
       
  1786     my $filestart = makeTestHeader($filecontent_ref, 1, REMOVE_SYMBIAN);
       
  1787 
       
  1788     if ($filestart =~ m/$NonNokiaCopyrPattern/is)
       
  1789     {
       
  1790         # There is Non-Nokia copyright statement in the file
       
  1791         if ($filestart =~ m/$testValueEpl/is)
       
  1792         {
       
  1793             # Non-Nokia file, but still EPL header
       
  1794             printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright with EPL$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1795             $verifyFailedCount[VERI_UNCLEAR_COPYR]++;
       
  1796             return 0;
       
  1797         }
       
  1798         elsif ($$filecontent_ref =~ m/$OldNokiaPattern2/is) 
       
  1799         {
       
  1800             printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Old Nokia copyright$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1801             $verifyFailedCount[VERI_OLD_NOKIA_HEADER]++;
       
  1802             return 0;
       
  1803         }
       
  1804         else
       
  1805         {
       
  1806             # Non-Nokia file
       
  1807             my $failReason = "";
       
  1808             if (!checkPortionsCopyright($filecontent_ref, 1, \$failReason))
       
  1809             {
       
  1810                 printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright$failReason$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1811                 $verifyFailedCount[VERI_UNCLEAR_COPYR]++;
       
  1812                 return 0;
       
  1813             }
       
  1814             else
       
  1815             {
       
  1816                 # Contains portions copyright
       
  1817                 printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1818                 return 1;
       
  1819             }
       
  1820         }
       
  1821     }
       
  1822 
       
  1823     #
       
  1824     # OK, it should be Nokia copyrighted file
       
  1825     #
       
  1826 
       
  1827     # Note that partial headers are manually quoted in the declaration
       
  1828     # Otherwise \Q$EPLText\E would be needed around those ones
       
  1829     # because plain text contains special chars, like .
       
  1830     printLog(LOG_DEBUG, "handleVerify testheaders: $testValueEpl,$$header_ref\n");
       
  1831 
       
  1832     if ( !( ($$header_ref =~ m/$testValueEpl/s) || ($$filecontent_ref =~ m/$testValueEpl/s) ) )
       
  1833     {
       
  1834         # Header not found from header or whole file
       
  1835        if (isGeneratedHeader($header_ref) || isGeneratedHeader($filecontent_ref))
       
  1836        {
       
  1837             # OK, it is generated header
       
  1838             if ($optOutputOK)
       
  1839             {
       
  1840                 printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "Generated header$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1841             }
       
  1842             $verifyFailedCount[VERI_OK]++;
       
  1843             return 1;  # OK
       
  1844        }
       
  1845 
       
  1846         if (($$header_ref =~ m/$testValueSfl/s) || ($$filecontent_ref =~ m/$testValueSfl/s))
       
  1847         {
       
  1848             #  Still SFL header in place
       
  1849             printResult(HEADER_CONTEXT() . "$sep"."EPL header missing (SFL header used)$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1850         }
       
  1851         elsif (($$header_ref =~ m/$OldNokiaPattern2/is) || ($$filecontent_ref =~ m/$OldNokiaPattern2/is))
       
  1852         {
       
  1853             printResult(HEADER_CONTEXT() . "$sep"."EPL header missing (old Nokia copyright)$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1854         }
       
  1855         else
       
  1856         {
       
  1857             printResult(HEADER_CONTEXT() . "$sep"."EPL header missing$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1858         }
       
  1859         $verifyFailedCount[VERI_MISSING_HEADER]++;
       
  1860         return 0;
       
  1861     }
       
  1862 
       
  1863     # Cross header versus distribution ID
       
  1864     if ($lastDistributionValue ne "")
       
  1865     {
       
  1866         # Also other than 7 may be OK based on the config file
       
  1867         my $isSFId = &isSFDistribution($lastDistributionValue);
       
  1868         printLog(LOG_DEBUG, "DEBUG:handleVerify:Other ID OK=$isSFId\n");
       
  1869         if ( ($$filecontent_ref =~ m/$testValueEpl/s) && ($lastDistributionValue ne EPL_DISTRIBUTION_VALUE) )
       
  1870         {
       
  1871             printResult(HEADER_CONTEXT() . "$sep"."EPL header vs. distribution id ($lastDistributionValue) mismatch$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1872             $verifyFailedCount[VERI_ID_HEADER_MISMATCH]++;
       
  1873             return 0;
       
  1874         }
       
  1875     }
       
  1876 
       
  1877     if (!checkNoMultipleLicenses($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory))
       
  1878     {
       
  1879         printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$fullfilename$sep" ."1\n");
       
  1880         printLog(LOG_ERROR, "Multiple licenses:".  $fullfilename . "\n");
       
  1881         $verifyFailedCount[VERI_MULTIPLE_LICENSES]++;
       
  1882         return 0; # Failed
       
  1883     }
       
  1884 
       
  1885 
       
  1886     # We should have proper header in place 
       
  1887 
       
  1888     printLog(LOG_DEBUG, "handleVerify: $$filecontent_ref\n");
       
  1889     # Check New Nokia copyright pattern (added one sentence to the old one)
       
  1890     if (! (($$header_ref =~ m/$NewNokiaPattern/s) || ($$filecontent_ref =~ m/$NewNokiaPattern/s)) )
       
  1891     {
       
  1892         printResult(HEADER_CONTEXT() . "$sep"."Proper Nokia copyright statement missing$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1893         $verifyFailedCount[VERI_PROPER_COPYRIGHT]++;
       
  1894         return 0; # Failed
       
  1895     }
       
  1896 
       
  1897     if ($optOutputOK)
       
  1898     {
       
  1899         printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "OK$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1900     }
       
  1901     $verifyFailedCount[VERI_OK]++;
       
  1902 
       
  1903     return 1;
       
  1904 
       
  1905 }
       
  1906 
       
  1907 
       
  1908 
       
  1909 ##################################################
       
  1910 # Verify changes for LGPL headers
       
  1911 ##################################################
       
  1912 sub handleVerifyLgpl
       
  1913 {
       
  1914     my $filecontent_ref = shift;
       
  1915     my $header_ref = shift;
       
  1916     my $commentChar = shift;
       
  1917     my $fullfilename = shift;
       
  1918     my $directory = shift;
       
  1919 
       
  1920 	my $testValueLgpl = "";
       
  1921     my $FromLgplText = &partialHeaderOf(LGPL_LICENSE,$commentChar, \$testValueLgpl);
       
  1922 
       
  1923     if ($lastDistributionValue eq "")
       
  1924     {
       
  1925         # Distribution file may be empty if giving single file as input
       
  1926         # Read it
       
  1927         $lastDistributionValue = readDistributionValue($directory);
       
  1928     }
       
  1929 
       
  1930     printLog(LOG_DEBUG, "handleVerifyLgpl $fullfilename, $$header_ref\n");
       
  1931 
       
  1932     # Note that partial headers are manually quoted in the declaration
       
  1933     # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones
       
  1934     # because plain text contains special chars, like .
       
  1935     printLog(LOG_DEBUG, "handleVerifyLgpl testheaders: $testValueLgpl,$$header_ref\n");
       
  1936 
       
  1937     if ( !( ($$header_ref =~ m/$testValueLgpl/s) || ($$filecontent_ref =~ m/$testValueLgpl/s) )  )
       
  1938     {
       
  1939         # Header not found from header or whole file
       
  1940        if (isGeneratedHeader($header_ref) || isGeneratedHeader($filecontent_ref))
       
  1941        {
       
  1942             # OK, it is generated header
       
  1943             if ($optOutputOK)
       
  1944             {
       
  1945                 printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "Generated header$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1946             }
       
  1947             $verifyFailedCount[VERI_OK]++;
       
  1948             return 1;  # OK
       
  1949        }
       
  1950 
       
  1951         my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename);
       
  1952         if (($$header_ref =~ m/$OldNokiaPattern2/is) || ($$filecontent_ref =~ m/$OldNokiaPattern2/is))
       
  1953         {
       
  1954             printResult(HEADER_CONTEXT() . "$sep"."LGPL header missing (old Nokia copyright)$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1955         }
       
  1956         else
       
  1957         {
       
  1958             printResult(HEADER_CONTEXT() . "$sep"."LGPL header missing$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1959         }
       
  1960         $verifyFailedCount[VERI_MISSING_HEADER]++;
       
  1961         return 0;
       
  1962     }
       
  1963 
       
  1964     if (!checkNoMultipleLicenses($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory))
       
  1965     {
       
  1966         printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$fullfilename$sep" ."1\n");
       
  1967         printLog(LOG_ERROR, "Multiple licenses:".  $fullfilename . "\n");
       
  1968         $verifyFailedCount[VERI_MULTIPLE_LICENSES]++;
       
  1969         return 0; # Failed
       
  1970     }
       
  1971 
       
  1972 
       
  1973     if ($optOutputOK)
       
  1974     {
       
  1975         printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "OK$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n");
       
  1976     }
       
  1977 
       
  1978     $verifyFailedCount[VERI_OK]++;
       
  1979 
       
  1980     return 1;
       
  1981 
       
  1982 }
       
  1983 
       
  1984 
       
  1985 ##################################################
       
  1986 # Test if header is already OK
       
  1987 # NOTE ! If header need to be converted to a new format, the 
       
  1988 #        check must return FALSE !!!
       
  1989 ##################################################
       
  1990 sub checkHeader
       
  1991 {
       
  1992     my $filecontent_ref = shift;
       
  1993     my $header_ref = shift;
       
  1994     my $commentChar = shift;
       
  1995     my $fullfilename = shift;
       
  1996     my $directory = shift;
       
  1997     my $req_license_ref = shift;  # in/out !!!
       
  1998 
       
  1999 	my $testValueSfl = "";
       
  2000 	my $testValueEpl = "";
       
  2001 	my $testValueLgpl = "";
       
  2002 
       
  2003     my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl);
       
  2004     my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl);
       
  2005     my $FromLGPLText = &partialHeaderOf(LGPL_LICENSE,$commentChar, \$testValueLgpl);
       
  2006 
       
  2007     # Note that partial headers are manually quoted in the declaration
       
  2008     # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones
       
  2009     # because plain text contains special chars, like .
       
  2010 
       
  2011     my $retLicense = SFL_LICENSE; # default
       
  2012     my $testValue = $testValueSfl;
       
  2013 
       
  2014     if ($$req_license_ref == EPL_LICENSE)
       
  2015     {
       
  2016         $testValue = $testValueEpl;
       
  2017         $retLicense = EPL_LICENSE;
       
  2018     }
       
  2019     elsif ($$req_license_ref == LGPL_LICENSE)
       
  2020     {
       
  2021         $testValue = $testValueLgpl;
       
  2022         $retLicense = LGPL_LICENSE;
       
  2023     }
       
  2024 
       
  2025     my $ret = 0;
       
  2026     $ret = ($$header_ref =~ m/$testValue/s);
       
  2027     if (!$ret)
       
  2028     {
       
  2029         # Check the rest of file
       
  2030         $ret = ($$filecontent_ref =~ m/$testValue/s);
       
  2031     }
       
  2032 
       
  2033     printLog(LOG_DEBUG, "checkHeader return=$ret\n");
       
  2034 
       
  2035     if ($ret)
       
  2036     {
       
  2037         $$req_license_ref = $retLicense;
       
  2038     }   
       
  2039 
       
  2040     return $ret;
       
  2041 }
       
  2042 
       
  2043 
       
  2044 ##################################################
       
  2045 # Test if file does not contain multiple licenses
       
  2046 # Returns 0 if test failed
       
  2047 ##################################################
       
  2048 sub checkNoMultipleLicenses
       
  2049 {
       
  2050     my $filecontent_ref = shift;
       
  2051     my $header_ref = shift;
       
  2052     my $commentChar = shift;
       
  2053     my $fullfilename = shift;
       
  2054     my $directory = shift;
       
  2055 
       
  2056     my $usedLicense = SFL_LICENSE;
       
  2057     my $licenseCnt = 0;
       
  2058     if (checkHeader($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory, \$usedLicense))
       
  2059     {
       
  2060         printLog(LOG_DEBUG, "checkNoMultipleLicenses SFL: $fullfilename\n");
       
  2061         $licenseCnt++;
       
  2062     }
       
  2063 
       
  2064     $usedLicense = EPL_LICENSE;
       
  2065     if (checkHeader($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory, \$usedLicense))
       
  2066     {
       
  2067         printLog(LOG_DEBUG, "checkNoMultipleLicenses EPL: $fullfilename\n");
       
  2068         $licenseCnt++;
       
  2069     }
       
  2070 
       
  2071     $usedLicense = LGPL_LICENSE;
       
  2072     if (checkHeader($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory, \$usedLicense))
       
  2073     {
       
  2074         printLog(LOG_DEBUG, "checkNoMultipleLicenses LGPL: $fullfilename\n");
       
  2075         $licenseCnt++;
       
  2076     }
       
  2077 
       
  2078     if ($licenseCnt > 1)
       
  2079     {
       
  2080         return 0; # check failed
       
  2081     }
       
  2082     return 1;
       
  2083 }
       
  2084 
       
  2085 ##################################################
       
  2086 # Change distribution value
       
  2087 # Can also be called with empty file content
       
  2088 ##################################################
       
  2089 sub handleDistributionValue
       
  2090 {
       
  2091     my $filecontent_ref = shift;
       
  2092     my $filename = shift;
       
  2093     my $content = $$filecontent_ref;
       
  2094 
       
  2095     if ($optVerify)
       
  2096     {
       
  2097         # Ignored
       
  2098         return LICENSE_NONE;
       
  2099     }
       
  2100 
       
  2101     $content =~ s/\n//g;  # Remove all new-lines
       
  2102     $content =~ s/^\s+//g;  # trim left
       
  2103     $content =~ s/\s+$//g;  # trim right
       
  2104 
       
  2105     if ($content ne "" && $content ne ZERO_DISTRIBUTION_VALUE)
       
  2106     {
       
  2107         if ($optEpl && ($content eq SFL_DISTRIBUTION_VALUE ))
       
  2108         {
       
  2109             # Allow  switching SFL to EPL
       
  2110             $$filecontent_ref = EPL_DISTRIBUTION_VALUE; 
       
  2111             printLog(LOG_INFO, "Distribution value changed from $content to $$filecontent_ref: $filename\n");        
       
  2112             return LICENSE_CHANGED;
       
  2113         }
       
  2114         else
       
  2115         {
       
  2116            # Otheriwise do not touch non-zero files ! (agreed with build team)
       
  2117            $ignoreCount++;
       
  2118            return LICENSE_NONE;
       
  2119        }
       
  2120     }
       
  2121 
       
  2122     if ($optOem)
       
  2123     {
       
  2124         # Leave existing (or missing) value as it was
       
  2125         return LICENSE_NONE;
       
  2126     }
       
  2127     elsif ($optEpl)
       
  2128     {
       
  2129         $$filecontent_ref = EPL_DISTRIBUTION_VALUE; 
       
  2130         printLog(LOG_INFO, "Distribution value changed from $content to $$filecontent_ref: $filename\n"); 
       
  2131         return LICENSE_CHANGED;
       
  2132     }
       
  2133     else  # SFL
       
  2134     {
       
  2135         $$filecontent_ref = SFL_DISTRIBUTION_VALUE; 
       
  2136         printLog(LOG_INFO, "Distribution value changed from $content to $$filecontent_ref: $filename\n");        
       
  2137         return LICENSE_CHANGED;
       
  2138     }
       
  2139 
       
  2140     return LICENSE_NONE;
       
  2141 
       
  2142 }
       
  2143 
       
  2144 ##################################################
       
  2145 # Select proper 
       
  2146 ##################################################
       
  2147 sub licenceIdForOption
       
  2148 {
       
  2149     if ($optEpl)
       
  2150     {
       
  2151         return EPL_LICENSE;
       
  2152     }
       
  2153     elsif ($optLgpl)
       
  2154     {
       
  2155         return LGPL_LICENSE;
       
  2156     }
       
  2157     else  # Must be
       
  2158     {
       
  2159         return SFL_LICENSE;
       
  2160     }
       
  2161 }
       
  2162 
       
  2163 
       
  2164 ##################################################
       
  2165 # Select proper header
       
  2166 ##################################################
       
  2167 sub headerOf
       
  2168 {
       
  2169     my $style = shift;
       
  2170 
       
  2171     if ($style < 0 || $style > 1)
       
  2172     {
       
  2173         printLog(LOG_ALWAYS, "INTERNAL ERROR: Header index out of bounds:$style. Exiting.\n");
       
  2174         exit 1;
       
  2175     }
       
  2176 
       
  2177     my $ref;
       
  2178     if ($optEpl)
       
  2179     {
       
  2180         $ref = $EplHeaders[$style];
       
  2181     }
       
  2182     elsif ($optLgpl)
       
  2183     {
       
  2184         $ref = $LgplHeaders[$style];
       
  2185     }
       
  2186     else  # SFL
       
  2187     {
       
  2188         $ref = $SflHeaders[$style];
       
  2189     }
       
  2190 
       
  2191     # Return the actual value
       
  2192     return $$ref;
       
  2193 }
       
  2194 
       
  2195 ##################################################
       
  2196 # Select proper partial header
       
  2197 ##################################################
       
  2198 sub partialHeaderOf
       
  2199 {
       
  2200     my $license = shift;
       
  2201     my $commentChar = shift;
       
  2202     my $testValue_ref = shift;
       
  2203 
       
  2204     my $ref;
       
  2205     my $ref2;
       
  2206     if ($license eq EPL_LICENSE)
       
  2207     {
       
  2208         $ref = $EplHeaders[2];
       
  2209         $ref2 = $EplHeaders[3]; 
       
  2210     }
       
  2211     elsif ($license eq S60_LICENSE)
       
  2212     {
       
  2213         $ref = $S60Headers[2];
       
  2214         $ref2 = $S60Headers[3];
       
  2215     }
       
  2216     elsif ($license eq LGPL_LICENSE)
       
  2217     {
       
  2218         $ref = $LgplHeaders[2];
       
  2219         $ref2 = $LgplHeaders[3];
       
  2220     }
       
  2221     elsif ($license eq SFL_LICENSE)
       
  2222     {
       
  2223         # SFL License
       
  2224         $ref = $SflHeaders[2];
       
  2225         $ref2 = $SflHeaders[3];  # return value 
       
  2226     }
       
  2227     else
       
  2228     {
       
  2229         printLog(LOG_ALWAYS, "INTERNAL ERROR: Invalid license parameter :$license. Exiting.\n");
       
  2230         exit 1;
       
  2231     }
       
  2232 
       
  2233     # Switch to proper comment char
       
  2234     my $ret = $$ref;
       
  2235     $ret =~ s/$CC/$commentChar/g;  # Replace the proper comment starter character
       
  2236 
       
  2237     # Return values
       
  2238     $$testValue_ref = $$ref2;
       
  2239     return $ret;
       
  2240 }
       
  2241 
       
  2242 
       
  2243 ##################################################
       
  2244 # Print result line
       
  2245 ##################################################
       
  2246 sub normalizeCppComment
       
  2247 {
       
  2248     my $header_regexp2 = shift;
       
  2249     my $filecontent = shift;
       
  2250     my $oldheader_ref = shift;  # in/out
       
  2251 
       
  2252 
       
  2253     # Normalize the C++ header syntax back to C++ in the file content
       
  2254     # in order to standardize stuff later on
       
  2255     $$oldheader_ref =~ s/(\/){3,}/\/\//g;  # replace ///+ back to //
       
  2256     $$oldheader_ref =~ s/\/\//*/g;  # Replace now // with *
       
  2257     $$oldheader_ref = "/*\n" . $$oldheader_ref . "*/\n";  # Add /* and */ markers
       
  2258 
       
  2259     # Created saved modified file content into memory
       
  2260     # This is the best way to do this.
       
  2261     my $ret = $filecontent;
       
  2262     $ret =~ s/$header_regexp2/$$oldheader_ref/;   # Note /s not used by purpose !
       
  2263     return $ret;
       
  2264 }
       
  2265 
       
  2266 
       
  2267 
       
  2268 ##################################################
       
  2269 # Print result line
       
  2270 ##################################################
       
  2271 sub printResult
       
  2272 {
       
  2273     my $text = shift;
       
  2274 
       
  2275     if ($outputfile)
       
  2276     {
       
  2277         print OUTPUT $text;
       
  2278     }
       
  2279     else
       
  2280     {
       
  2281         print $text;
       
  2282     }
       
  2283 
       
  2284     printLog(LOG_DEBUG(), $text);
       
  2285 
       
  2286 }
       
  2287 
       
  2288 ##################################################
       
  2289 # Print log line
       
  2290 ##################################################
       
  2291 sub printLog
       
  2292 {
       
  2293     my $loglevel = shift;
       
  2294     my $text = shift;
       
  2295 
       
  2296     if ($loglevel > $optLogLevel) 
       
  2297     {
       
  2298         return;  # No logging
       
  2299     }
       
  2300     if ($logFile) 
       
  2301     {
       
  2302         print LOG $LOGTEXTS[$loglevel] . $text;
       
  2303     }
       
  2304 
       
  2305     return 0;
       
  2306 }
       
  2307 
       
  2308 
       
  2309 ##################################################
       
  2310 # Print log line
       
  2311 ##################################################
       
  2312 sub printLogStatisticNumber
       
  2313 {
       
  2314     my $number = shift;
       
  2315     my $loglevel = shift;  
       
  2316     my $text = shift;  # Should contains %d where to put the number
       
  2317 
       
  2318     if ($number == 0)
       
  2319     {
       
  2320         return;  # No logging
       
  2321     }
       
  2322 
       
  2323     if ($text =~ m/\%d/)
       
  2324     {
       
  2325         $text =~ s/\%d/$number/;
       
  2326     }
       
  2327     else 
       
  2328     {
       
  2329         # Add number to the beginning of text
       
  2330         $text = $number . " " . $text;
       
  2331     }   
       
  2332    
       
  2333     if ($loglevel > $optLogLevel) 
       
  2334     {
       
  2335         return;  # No logging
       
  2336     }
       
  2337     if ($logFile) 
       
  2338     {
       
  2339         print LOG $LOGTEXTS[$loglevel] . $text;
       
  2340     }
       
  2341 
       
  2342     return 0;
       
  2343 }
       
  2344 
       
  2345 
       
  2346 ##################################################
       
  2347 # Read the content of old output
       
  2348 ##################################################
       
  2349 sub readOldOutput
       
  2350 {
       
  2351     my($filename) = shift;
       
  2352     my $fh = new FileHandle "<$filename";
       
  2353     if (!defined($fh))
       
  2354     {
       
  2355         printLog(LOG_ERROR, "Could not open file $filename for read\n");
       
  2356         return;
       
  2357     }
       
  2358 
       
  2359     my  @lines = <$fh>;
       
  2360     my $line;
       
  2361     foreach $line (@lines)
       
  2362     {
       
  2363        my (@parts) = split(/\,/,$line);  # Split line with "," separator
       
  2364        if ($parts[2] =~ m/$IGNORE_MAN/i)
       
  2365        {
       
  2366             my $fullfilename = lc($parts[4]);
       
  2367             $fullfilename =~ s/\\/\//g;  # Standardize name 
       
  2368             $manualIgnoreFileHash{$fullfilename} = "1" ;  # Just some value
       
  2369             printLog(LOG_DEBUG, "Manually ignoring file:$fullfilename\n");
       
  2370        }
       
  2371     }
       
  2372 
       
  2373     close ($fh);
       
  2374 }
       
  2375 
       
  2376 ##################################################
       
  2377 # Read configuation file which has  the format:
       
  2378 # sf-update-licence-header-config-1.0
       
  2379 ##################################################
       
  2380 sub readConfig
       
  2381 {
       
  2382     my ($fname) = @_;
       
  2383 
       
  2384     open(IN,$fname) || die "Unable to open file: \"$fname\" for reading.";
       
  2385     LINE:
       
  2386     while(<IN>) 
       
  2387     {
       
  2388         chomp;
       
  2389         # tr/A-Z/a-z/;  # Do not lowercase pattern
       
  2390         my $line = $_;
       
  2391         $line =~ s/^\s+//;  # trim left
       
  2392         $line =~ s/\s+$//;  # trim right
       
  2393         
       
  2394         next LINE if length($line) == 0; # # Skip empty lines
       
  2395         next LINE if ($line =~ /^\#.*/); # Skip comments;
       
  2396 
       
  2397         if ($line =~ /^sf-update-licence-header-config.*/i) 
       
  2398         {
       
  2399             my ($tmp1, $tmp2) = split(/sf-update-licence-header-config-/,$line);  # Get version
       
  2400             $configVersion = $tmp2;
       
  2401         }
       
  2402         elsif ($line =~ /^sf-distribution-id/i) 
       
  2403         {
       
  2404             my ($tmp, @parts) = split(/[\s\t]+/,$line); # space as separator
       
  2405             my $cnt = @parts;
       
  2406             push(@sfDistributionIdArray, @parts);
       
  2407             my $cnt = @sfDistributionIdArray;
       
  2408             printLog(LOG_DEBUG, "readConfig:sfDistributionIdArray count:$cnt\n");
       
  2409         }
       
  2410         elsif ($line =~ /^sf-generated-header/i) 
       
  2411         {
       
  2412             my ($tmp, @parts) = split(/[\s\t]+/,$line); # space as separator
       
  2413             my $cnt = @parts;
       
  2414             push(@sfGeneratedPatternArray, @parts);
       
  2415             my $cnt = @sfGeneratedPatternArray;
       
  2416             printLog(LOG_DEBUG, "readConfig:sfGeneratedPatternArray count:$cnt\n");
       
  2417         }
       
  2418     }
       
  2419 
       
  2420     # Pre-compile here the source line pattern
       
  2421     close (IN);
       
  2422 }
       
  2423 
       
  2424 
       
  2425 ##################################################
       
  2426 # Test  ID is under SF distribution
       
  2427 ##################################################
       
  2428 sub isSFDistribution
       
  2429 {
       
  2430     my $id = shift;
       
  2431 
       
  2432     if (($id == SFL_DISTRIBUTION_VALUE) || ($id == EPL_DISTRIBUTION_VALUE))
       
  2433     {
       
  2434         # Implicit case
       
  2435         return 1;
       
  2436     }
       
  2437 
       
  2438     my $otherOkId = grep { $_ eq $id } @sfDistributionIdArray;  # Use exact match
       
  2439     return $otherOkId;
       
  2440 }
       
  2441 
       
  2442 ##################################################
       
  2443 # Test header contains generated file pattern
       
  2444 ##################################################
       
  2445 sub isGeneratedHeader
       
  2446 {
       
  2447     my $header_ref = shift;
       
  2448 
       
  2449     my $count = grep { $$header_ref =~ m/$_/is } @sfGeneratedPatternArray;
       
  2450     return $count;
       
  2451 }
       
  2452 
       
  2453 
       
  2454 ##################################################
       
  2455 #                   MAIN
       
  2456 ##################################################
       
  2457 
       
  2458 GetOptions(
       
  2459 	'h|help' => \$help,     #print help message
       
  2460 	'm|modify' => \$optModify,   #Allow modifications
       
  2461 	'c|create' => \$optCreate,   #Create missing file
       
  2462 	'output:s' => \$outputfile,   #Output (result) file
       
  2463 	'ignorefile:s' => \$ignorefilepattern,   #Ignore file pattern
       
  2464 	'oldoutput:s' => \$oldOutputFile,   #Old output file
       
  2465     'log:s' => \$logFile,         # Log file
       
  2466     'verbose:i' => \$optLogLevel, # Logging level
       
  2467     'epl' => \$optEpl,  # Switch file header to EPL one
       
  2468     'lgpl' => \$optLgpl,  # Switch file header LGPL v2.1
       
  2469     'oem' => \$optOem,  # Switch back S60 header for OEM release. 
       
  2470     'eula' => \$optOem,  # Switch back S60 header for EULA (End-User License Agreement) release. Same as OEM
       
  2471     'append' => \$optAppend,  # Append result files
       
  2472     'verify' => \$optVerify,  # Verifies files has correct header
       
  2473     'configfile:s' => \$configFile,
       
  2474     'description!' => \$optDescription,  # output missing description
       
  2475     'okoutput!' => \$optOutputOK  # output also OK entries
       
  2476 	);
       
  2477 
       
  2478 die $usage if $#ARGV<0;
       
  2479 die $usage if $help;
       
  2480 
       
  2481 if ($logFile) 
       
  2482 {
       
  2483     my $openmode = ">" . ($optAppend ? ">" : "");
       
  2484     open (LOG, "$openmode$logFile") || die "Couldn't open $openmode$logFile\n";  # Can not call printLog
       
  2485     LOG->autoflush(1);  # Force flush
       
  2486 }
       
  2487 
       
  2488 printLog(LOG_INFO, "========================\n");
       
  2489 
       
  2490 if ($oldOutputFile && $optVerify)
       
  2491 {
       
  2492     readOldOutput($oldOutputFile);
       
  2493 }
       
  2494 
       
  2495 if (!$configFile) 
       
  2496 {
       
  2497     $configFile = "$Bin/SFUpdateLicenceHeader.cfg";
       
  2498 }
       
  2499 
       
  2500 if ($configFile && -e $configFile) 
       
  2501 {
       
  2502     &readConfig($configFile);
       
  2503 }
       
  2504 
       
  2505 if (!$ignorefilepattern)
       
  2506 {
       
  2507     # Set decent default value
       
  2508     if ($optOem)
       
  2509     {
       
  2510         # Scan through internal stuff all source dirs just in case
       
  2511         $ignorefilepattern = "(_ccmwaid\.inf|\.svn)";
       
  2512     }
       
  2513     else
       
  2514     {
       
  2515         $ignorefilepattern = "(abld\.bat|_ccmwaid\.inf|\.svn|/docs/|/internal/|/doc/)";
       
  2516     }
       
  2517 }
       
  2518 
       
  2519 if ($optEpl)
       
  2520 {
       
  2521     printLog(LOG_INFO, "Option -epl used\n");
       
  2522 }
       
  2523 if ($optLgpl)
       
  2524 {
       
  2525     printLog(LOG_INFO, "Option -lgpl used\n");
       
  2526 }
       
  2527 if ($optOem)
       
  2528 {
       
  2529     printLog(LOG_INFO, "Option -oem used\n");
       
  2530     # Modify ignore to contain also internal dirs just in case
       
  2531 }
       
  2532 if ($optModify)
       
  2533 {
       
  2534     printLog(LOG_INFO, "Option -modify used\n");
       
  2535 }
       
  2536 if ($optVerify)
       
  2537 {
       
  2538     printLog(LOG_INFO, "Option -verify used\n");
       
  2539 }
       
  2540 if ($optCreate)
       
  2541 {
       
  2542     printLog(LOG_INFO, "Option -create used\n");
       
  2543 }
       
  2544 
       
  2545 if ($ignorefilepattern)
       
  2546 {
       
  2547     printLog(LOG_INFO, "Option -ignorefile has value: $ignorefilepattern\n");
       
  2548 }
       
  2549 
       
  2550 my $startTime = time;
       
  2551 
       
  2552 if ($outputfile) 
       
  2553 {
       
  2554     my $openmode = ">" . ($optAppend ? ">" : "");
       
  2555     open (OUTPUT, "$openmode$outputfile") || die "Couldn't open $outputfile\n";
       
  2556     OUTPUT->autoflush(1);  # Force flush
       
  2557 }
       
  2558 
       
  2559 if (! -e $ARGV[0] )
       
  2560 {
       
  2561     printLog(LOG_ERROR, "$ARGV[0] not found\n");
       
  2562     if ($logFile)
       
  2563     {
       
  2564         close LOG; 
       
  2565     }
       
  2566     exit(1);
       
  2567 }
       
  2568 
       
  2569 printLog(LOG_INFO,"SFUpdateLicenceHeader.pl version " . VERSION . " statistics:\n");
       
  2570 printLog(LOG_INFO, "Directory/file=@ARGV\n");
       
  2571 
       
  2572 #
       
  2573 # Process files in the given directory recursively
       
  2574 #
       
  2575 # NOTE : "no_chdir" option not used --> find changes the current working directory 
       
  2576 find({ wanted => \&process_file, postprocess => \&postprocess, preprocess => \&preprocess },  @ARGV);
       
  2577 
       
  2578 if ($outputfile)
       
  2579 {
       
  2580     close OUTPUT;
       
  2581 }
       
  2582 
       
  2583 my $elapsedTime = time - $startTime;
       
  2584 
       
  2585 printLogStatisticNumber($fileCount, LOG_INFO, "%d files checked\n") ;
       
  2586 if ($optModify)
       
  2587 {
       
  2588     printLogStatisticNumber($modifiedFileCount, LOG_INFO, "%d files modified \n") ;
       
  2589 }
       
  2590 else
       
  2591 {
       
  2592     printLogStatisticNumber($willModifiedFileCount, LOG_INFO, "%d will be modified \n") ;
       
  2593 }
       
  2594 printLogStatisticNumber($ignoreCount, LOG_INFO, "%d files ignored.\n") ;
       
  2595 printLogStatisticNumber($unrecogCount, LOG_INFO, "%d files not recognized.\n") ;
       
  2596 if ($optVerify)
       
  2597 {
       
  2598     for (my $i=0; $i < @verifyFailedCountMsgs; $i++)
       
  2599     {
       
  2600        printLogStatisticNumber($verifyFailedCount[$i], LOG_INFO, "Verify statistics:$verifyFailedCountMsgs[$i]=%d.\n") ;
       
  2601     }
       
  2602 }
       
  2603 elsif (!$optOem)
       
  2604 {
       
  2605     printLogStatisticNumber($noDescrcount, LOG_INFO, "%d files has no Description.\n") ;
       
  2606     printLogStatisticNumber($NokiaCopyrCount, LOG_INFO, "%d files has Nokia copyright.\n") ;
       
  2607     printLogStatisticNumber($ExternalToNokiaCopyrCount, LOG_INFO, "%d files moved also to Nokia.\n") ;
       
  2608     printLogStatisticNumber($otherCopyrCount, LOG_INFO, "%d files has non-nokia copyright.\n") ;
       
  2609     printLogStatisticNumber($NoCopyrCount, LOG_INFO, "%d files has no copyright.\n") ;
       
  2610     printLogStatisticNumber($UnclearCopyrCount, LOG_INFO, "%d files has UNCLEAR copyright.\n") ;
       
  2611     printLogStatisticNumber($createCount, LOG_INFO, "%d new files.\n") ;
       
  2612     if ($optEpl)
       
  2613     {
       
  2614         printLogStatisticNumber($SflToEplChanges, LOG_INFO, "%d files changes from SFL to EPL license.\n") ;
       
  2615     }
       
  2616     else
       
  2617     {
       
  2618         printLogStatisticNumber($EplToSflChanges, LOG_INFO, "%d files changes from SFL to EPL license.\n") ;
       
  2619     }
       
  2620 }
       
  2621 else
       
  2622 {
       
  2623     printLogStatisticNumber($SflToS60Changes, LOG_INFO, "%d files changes from SFL to S60 license.\n") ;
       
  2624     # printLog($EplToS60Changes, LOG_INFO, "%d files changes from EPL to S60 license.\n") ;
       
  2625     printLogStatisticNumber($LicenseChangeErrors, LOG_INFO, "%d errors upon license change.\n") ;
       
  2626 }
       
  2627 
       
  2628 printLog(LOG_INFO,"Time elapsed $elapsedTime.\n") ;
       
  2629 
       
  2630 if ($logFile) 
       
  2631 {
       
  2632     close LOG;
       
  2633 }
       
  2634