diff -r a9d4531388d0 -r d90029decf65 bldsystemtools/commonbldutils/SFUpdateLicenceHeader.pl --- a/bldsystemtools/commonbldutils/SFUpdateLicenceHeader.pl Wed Mar 31 23:20:42 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2647 +0,0 @@ -# Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. -# This material, including documentation and any related -# computer programs, is protected by copyright controlled by -# Nokia. All rights are reserved. Copying, including -# reproducing, storing, adapting or translating, any -# or all of this material requires the prior written consent of -# Nokia. This material also contains confidential -# information which may not be disclosed to others without the -# prior written consent of Nokia. -# -# Contributors: -# matti.parnanen@nokia.com -# pasi.kauraniemi@nokia.com -# -# Description: Replace S60 header with Symbian Foundation license header. -# Output file (results) is compatibe for SFMakeLxrLinks.pl as input. -# -use strict; -use File::Find; -use File::Basename; -use Getopt::Long; -use IO::Handle; -use FindBin qw($Bin); -use FileHandle; - -#################### -# Constants -#################### - -# Tool version -use constant VERSION => '2.22'; -# Version history: 0.8 Added copyright year pick-up -# Version history: 0.9- Bug fixesg -# Version history: 0.95- EPL header support added -# Version history: 0.96 Minor script adjustments -# Version history: 0.97 Assembly files (.s, .cia, .asm) checked as well -# Version history: 0.98 Support for -oem added. Also @file tag removed from template -# Version history: 0.99 Testing -oem option -# Version history: 1.0 Comment column added for PostProcess script -# Version history: 1.01 Modify option bug fixed -# Version history: 1.1 Description bug fixed -# Version history: 1.2 Digia copyrights moved to SF as well. Also R/O attribute removed only for files modified -# Version history: 1.3 Distribution policy files handled as well. With -create also created -# Version history: 1.31 Fixes to distribution file handling (only non-empty directories acknowledged) -# Version history: 1.32 .pm files checked as well -# Version history: 1.4 Bug fixes and "ignorefile" agrument added -# Version history: 1.41 Bug fix in Description pick-up -# Version history: 1.42 Bug fix in -ignore option (also missing .s60 file creation need to be ignored). Default value set to ignore option -# Version history: 1.43 Description statistics fixed, .hpp added, description pick-up improved -# Version history: 1.5 -verify option implemented, ignorefile default value extended, statistics go to log -# Version history: 1.51 Copyright year pick-up bug fixed, ignorefilepattern comparison case-insensitive -# Version history: 1.52 current s60 dumped to result -# Version history: 1.53 abld.bat added ti ignorefile default -# Version history: 1.54 -verify statistics improved -# Version history: 1.55 -eula option added -# Version history: 1.56 .mmh files added, extra Non-Nokia check added for "No Copyright" case for weired headers -# Version history: 1.57 Changes to -verify -# Version history: 1.58 @echo on ... @echo off added to .cmd and .bat headers -# Version history: 1.59 EPL warning log entry --> info -# Version history: 1.60 and 1.61 -ignorelist option added -# Version history: 1.62 Uppercase REM text allowed -# Version history: 1.63 Internal directory check added to -verify -# Version history: 1.64 Symbian --> Symbian.*Ltd in $ExternalToNokiaCopyrPattern -# Version history: 1.65 Bug fixed in normalizeCppComment -# Version history: 1.70 Changes to better cope with ex-Symbian sources, -# Pasi's better "@rem" taken into use for .bat and .cmd files -# Version history: 1.71 Config file support added (option -config) for non 3/7 IDs -# Version history: 1.72 handleVerify checks improved to include also file start -# Version history: 1.73 \b added to Copyright word to reduce if "wrong" alarms -# Version history: 1.74 incomplete copyright check added to -verify -# Version history: 1.75 Support for ignoring generated headers (@sfGeneratedPatternArray) added -# Version history: 1.76 .script extension added (using Cpp comments e.g. // Text) -# Version history: 1.77 Reporting and logging improvements for wk19 checks (need to check / patch single files) -# Version history: 1.80 Few Qt specific file extensions added, -lgpl option added, -# C++ comment fix in handleOem -# Version history: 1.90 checkNoMultipleLicenses function added, and call to handleVerify* added -# Version history: 2.0 handleDistributionValue() changes IDs 0-->3/7 and 3-->7, -# isGeneratedHeader() checks for file content added. -# Version history: 2.01 checkPortionsCopyright implemented and applied -# Version history: 2.02 Extra license word taken out from EPL header -# Version history: 2.1 -verify -epl support added and switchLicense() tried first for SFL --> EPL switching -# Version history: 2.20 Bug fixes. - -my $IGNORE_MAN ='Ignore-manually'; -my $IGNORE ='Ignore'; -my $INTERNAL = '/internal/'; -use constant KEEP_SYMBIAN => 0; -use constant REMOVE_SYMBIAN => 1; - - -#file extention list that headers should be replace -my @extlist = ('.cpp', '.c', '.h', '.mmp', '.mmpi', '.rss', '.hrh', '.inl', '.inf', '.iby', '.oby', - '.loc', '.rh', '.ra', '.java', '.mk', '.bat', '.cmd', '.pkg', '.rls', '.rssi', '.pan', '.py', '.pl', '.s', '.asm', '.cia', - '.s60', '.pm', '.hpp', '.mmh', '.script', '.mrp', - '.pro', '.pri'); # Qt specific - -# Various header comment styles -my @header_regexps = -( -'^\s*(\#.*?\n)*', # Perl, Python -'^\s*(\@echo\s*off\s*\n)?\n*(@?(?i)rem.*?\n)*(\@echo\s*on\s*)?', # Windows command script -'^\s*(\;.*?\n)*', # SIS package file -'\s*\/\*[\n\s\*-=].*?\*\/', # C comment block -'(\s*\/\/.*\n)+', # C++ comment block (do not use /s in regexp evaluation !!!) -'^\s*((\/\/|\#).*?\n)*' # Script file comment -); - -# Comment regular expression (Indeces within @header_regexps) -use constant COMMENT_PERL => 0; -use constant COMMENT_CMD => 1; -use constant COMMENT_SIS_ASM => 2; -use constant COMMENT_C => 3; -use constant COMMENT_CPP => 4; -use constant COMMENT_SCRIPT => 5; - -my $descrTemplateOnly = '\?Description'; -my $linenumtext = "1"; # Use this linenumer in LXR links - -# Copyright patterns -my $copyrYearPattern = 'Copyright\b.*\d{4}\s*([,-]\s*\d{4})*'; -my $copyrYearPattern2 = '\d{4}(\s*[,-]\s*\d{4})*'; -use constant DEFCOPYRIGHTYEAR => "2010"; # For error cases - -my $NokiaCopyrPattern = '\bCopyright\b.*Nokia.*(All Rights)?'; -my $NonNokiaCopyrPattern = '\bCopyright\b.*(?!Nokia).*(All Rights)?'; -my $CopyrPattern = '\bCopyright\b'; -my $RemoveS60TextBlockPattern = 'This material.*Nokia'; -my $CC = 'CCHAR'; -my $BeginLicenseBlockPattern = 'BEGIN LICENSE BLOCK'; -my $OldNokiaPattern = 'Nokia\s*Corporation[\.\s]*\n'; -my $NewNokiaText = "Nokia Corporation and/or its subsidiary(-ies).\n"; # Used in substitu to text -my $NewNokiaPattern = "Nokia Corporation and/or its subsidiary"; -my $OldNokiaPattern2 = "This material.*including documentation and any related.*protected by copyright controlled.*Nokia"; -my $PortionsNokiaCopyrPattern = 'Portions.*Copyright\b.*Nokia.*(All Rights)?'; -my $NewPortionsNokiaCopyrPattern = 'Portions\s*Copyright\b.*' . $NewNokiaPattern; - -# Move these copyrights to Nokia !!! -my $ExternalToNokiaCopyrPattern = 'Copyright\b.*(Symbian\sLtd|Symbian\s*Software\s*Ltd|Digia|SysopenDigia).*(All\s+Rights|All\s+rights)?'; -my $PortionsSymbianCopyrPattern = 'Portions\s*Copyright\b.*(Symbian\sLtd|Symbian\s*Software\s*Ltd).*(All\s+Rights|All\s+rights)?'; - -############### -# SFL headers -############### -# SFL C/C++ style -# -my $SFLicenseHeader = -'/* -* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: -* -*/'. "\n"; - -# Test string to test header have been changed -my $SFLHeaderTest = 'Symbian\s*Foundation\s*License.*www\.symbianfoundation\.org\/legal\/sfl'; - -# Partial SFL header template (# will be replaced by actual comment syntax char) -# Prepare for cases where someone adds spaces to string. -my $SFLicenseHeaderPartial_template = -$CC . '\s*This\s*component\s*and\s*the\s*accompanying\s*materials\s*are\s*made\s*available\s*\n' . -$CC . '\s*under\s*the\s*terms\s*of\s*the\s*License\s*\"Symbian\s*Foundation\s*License\s*v1\.0\"\s*\n' . -$CC . '\s*which\s*accompanies\s*this\s*distribution\,\s*and\s*is\s*available\s*\n' . -$CC . '\s*at\s*the\s*URL\s*\"http\:\/\/www\.symbianfoundation\.org\/legal\/sfl\-v10\.html\"\s*\.'; - -# SFL other comment styles (replace # with actual comment starter) -# -my $SFLicenseHeader_other_template = -'# -# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. -# This component and the accompanying materials are made available -# under the terms of the License "Eclipse Public License v1.0" -# which accompanies this distribution, and is available -# at the URL "http://www.eclipse.org/legal/epl-v10.html". -# -# Initial Contributors: -# Nokia Corporation - initial contribution. -# -# Contributors: -# -# Description: -# -'; - - - -############### -# EPL headers -############### -# C/C++ style -my $EPLLicenseHeader = -'/* -* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: -* -*/' . "\n"; - -# Test string to test header have been changed -my $EPLHeaderTest = 'Eclipse\s*Public\s*License.*www\.eclipse\.org\/legal\/epl'; - -# Partial EPL header (replace # with actual comment starter) -# Prepare for cases where someone adds spaces to string. -my $EPLLicenseHeaderPartial_template = -$CC . '\s*This\s*component\s*and\s*the\s*accompanying\s*materials\s*are\s*made\s*available\s*\n' . -$CC . '\s*under\s*the\s*terms\s*of\s*\"Eclipse\s*Public\s*License\s*v1\.0\"\s*\n' . -$CC . '\s*which\s*accompanies\s*this\s*distribution,\s*and\s*is\s*available\s*\n' . -$CC . '\s*at\s*the\s*URL\s*\"http\:\/\/www\.eclipse\.org\/legal\/epl\-v10\.html\"\s*\.'; - - -# EPL other comment styles (replace # with comment starter) -# -my $EPLLicenseHeader_other_template = -'# -# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. -# This component and the accompanying materials are made available -# under the terms of "Eclipse Public License v1.0" -# which accompanies this distribution, and is available -# at the URL "http://www.eclipse.org/legal/epl-v10.html". -# -# Initial Contributors: -# Nokia Corporation - initial contribution. -# -# Contributors: -# -# Description: -# -'; - -############## -# LGPL headers -############## -my $LGPLLicenseHeader = -'/* -* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Lesser General Public License as published by -* the Free Software Foundation, version 2.1 of the License. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public License -* along with this program. If not, -* see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/". -* -* Description: -* -*/'; - -# Test string to test header have been changed -my $LGPLHeaderTest = 'GNU\s*Lesser\s*General\s*Public\s*License.*www\.gnu\.org\/licenses/old-licenses\/lgpl-2\.1\.html'; - -# Partial LGPL header (replace $CC with actual comment starter) -my $LGPLLicenseHeaderPartial_template = -$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' . -$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' . -$CC . '\s*the\s*Free\s*Software\s*Foundation\,\s*version\s*2\.1\s*of\s*the\s*License\n'; - - -# LGPL other comment styles (replace # with comment starter) -# -my $LGPLLicenseHeader_other_template = -'# -# Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). -# All rights reserved. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, version 2.1 of the License. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, -# see "http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html/". -# -# Description: -# -'; - - -############### -# S60 headers -############### -# C/C++ style -my $S60HeaderPartial_template = -$CC . " This material, including documentation and any related computer\n" . -$CC . " programs, is protected by copyright controlled by Nokia. All\n" . -$CC . " rights are reserved. Copying, including reproducing, storing\n" . -$CC . " adapting or translating, any or all of this material requires the\n" . -$CC . " prior written consent of Nokia. This material also contains\n" . -$CC . " confidential information which may not be disclosed to others\n" . -$CC . " without the prior written consent of Nokia."; - -# Test string to test header have been changed -my $S60HeaderTest = 'is\s*protected\s*by\s*copyright\s*controlled\s*by\s*Nokia'; - - -my @SflHeaders = (\$SFLicenseHeader, \$SFLicenseHeader_other_template, \$SFLicenseHeaderPartial_template, \$SFLHeaderTest); # contains refs -my @EplHeaders = (\$EPLLicenseHeader, \$EPLLicenseHeader_other_template, \$EPLLicenseHeaderPartial_template, \$EPLHeaderTest); # contains refs -my @S60Headers = (undef,undef,\$S60HeaderPartial_template, \$S60HeaderTest); # contains refs -my @LgplHeaders = (\$LGPLLicenseHeader, \$LGPLLicenseHeader_other_template, \$LGPLLicenseHeaderPartial_template, \$LGPLHeaderTest); # contains refs - -# Header styles (indeces within @SflHeaders and @EplHeaders) -use constant CPP_HEADER => 0; -use constant OTHER_HEADER => 1; - -# switchLicense related values -use constant SFL_LICENSE => 3; -use constant EPL_LICENSE => 7; -use constant S60_LICENSE => 0; -use constant LGPL_LICENSE => 4; -use constant LICENSE_CHANGED => 1; -use constant LICENSE_NONE => 0; -use constant LICENSE_ERROR => -1; -use constant LICENSE_NOT_SUPPORTED => -2; - -# Distribution policy file values -use constant INTERNAL_DISTRIBUTION_VALUE => "1"; -use constant ZERO_DISTRIBUTION_VALUE => "0"; -use constant SFL_DISTRIBUTION_VALUE => "3"; -use constant EPL_DISTRIBUTION_VALUE => "7"; # option -epl -use constant TSRC_DISTRIBUTION_VALUE => "950"; # -use constant NONSF_DISTRIBUTION_VALUE => "Other"; # -use constant DISTRIBUTION_FILENAME => "distribution.policy.s60"; - -my $usage = 'SFUpdateLicenHeader.pl tool, version: ' . VERSION . -' -Usages: - perl SFUpdateLicenceHeader.pl [-modify] [-epl] [-oem] [-create] [-ignorefile pattern] - [-output csv-file] [-log logfile] [-verbose level] [-verify] [-append] - [-oldoutput old-csv-file] DIRECTORY|FILE - - Check switch to SFL header in a directory (and subdirectories under that): - perl SFUpdateLicenceHeader.pl -output csv-file -log logfile DIRECTORY - Switch to SFL header and modify .policy.s60 files in a directory (and subdirectories under that): - perl SFUpdateLicenceHeader.pl -modify -output csv-file -log logfile DIRECTORY - Switch to SFL header and modify .policy.s60 files in a single file: - perl SFUpdateLicenceHeader.pl -modify -output csv-file -log logfile FILE - Switch to EPL header and modify .policy.s60 files: - perl SFUpdateLicenceHeader.pl -modify -epl -output csv-file -log logfile DIRECTORY - Switch to SFL header and modify/create missing .policy.s60 files: - perl SFUpdateLicenceHeader.pl -modify -create -output csv-file -log logfile DIRECTORY - Switch to SFL header and ignore files matching CCM file pattern: - perl SFUpdateLicenceHeader.pl -modify -ignore "_ccmwaid.inf" -output csv-file -log logfile DIRECTORY - Switch to SFL header and ignore files matching CCM or SVN file patterns: - perl SFUpdateLicenceHeader.pl -modify -ignore "(_ccm|.svn)" -output csv-file -log logfile DIRECTORY - Switch back to Nokia header (for OEM delivery team): - perl SFUpdateLicenceHeader.pl -modify -oem -output csv-file -log logfile DIRECTORY - Verify file header changes - perl SFUpdateLicenceHeader.pl -verify -output csv-file -log logfile DIRECTORY - Verify and append logs and results to single file - perl SFUpdateLicenceHeader.pl -verify -append -output AllResults.csv -log AllLogs.log DIRECTORY - Verify file header changes and use old result file as add-on configuation (used by -verbose only) - perl SFUpdateLicenceHeader.pl -verify -oldoutput old-csv-file -output csv-file -log logfile DIRECTORY - -For more info, see http://s60wiki.nokia.com/S60Wiki/SFDG-File-Header#SFUpdateLicenceHeader.pl -'; - -# Logging constants -use constant LOG_ALWAYS => 0; -use constant LOG_INFO => 3; -use constant LOG_ERROR => 1; -use constant LOG_WARNING => 2; -use constant LOG_DEBUG => 4; -my @LOGTEXTS = ("", "ERROR: ", "Warning: ", "Info: ", "DEBUG: "); -my $sep = ","; -my $logFile = ""; - -# Issue categories in result CSV formatted file -use constant HEADER_CONTEXT => 'header-issue'; -use constant DISTRIBUTION_CONTEXT => 'distribution-issue'; - - -#################### -# Global variables -#################### - -# Command line options -my $help = 0; -my $outputfile; -my $ignorefilepattern; # File patterns to ignore -# my $optSfl = 1; # By default sfl is on -my $optEpl = 0; # Use EPL headers -my $optLgpl = 0; # Use LGPL v2.1 headers -my $optLogLevel = LOG_INFO; -my $optModify = 0; # (default mode is check) -my $optCreate = 0; # (create missing files) -my $optOem = 0; # OEM delivery to S60 license -my $optAppend = 0; # Append results -my $optVerify = 0; # Verify option -my $oldOutputFile; # Version 1.60 old output file in CSV format -my %manualIgnoreFileHash; # Hash of files ignored -my $optDescription = 0; # Output also missing description -my $optOutputOK = 0; # Output also OK issues for -verify - -# The last distribution ID -my $lastDistributionValue = ""; - -# Config file specific gllobals -my $configFile; -my $configVersion = ""; -my @sfDistributionIdArray = (); # Distribution ID array -my @sfGeneratedPatternArray = (); # Distribution ID array - -# -# Statistics variables -# -my $fileCount = 0; -my $modifiedFileCount = 0; -my $willModifiedFileCount = 0; -my $noDescrcount = 0; -my $otherCopyrCount=0; -my $ExternalToNokiaCopyrCount=0; -my $NokiaCopyrCount=0; -my $NoCopyrCount=0; -my $UnclearCopyrCount=0; -my $SflToS60Changes = 0; -my $EplToS60Changes = 0; -my $SflToEplChanges = 0; -my $EplToSflChanges = 0; -my $LicenseChangeErrors = 0; -my $ignoreCount = 0; -my $unrecogCount = 0; -my $createCount = 0; -my @verifyFailedCount = (0,0,0,0,0,0,0,0,0,0,0); -my @verifyFailedCountMsgs = ("Distribution file missing", # Index 0 - "SFL or EPL distribution ID missing", #1 - "SFL or EPL header missing", #2 - "Proper copyright missing", #3 - "Header vs. distribution ID mismatch", #4 - "Internal directory going to SF", #5 - "Old Nokia file header used", #6 - "Unclear Non-Nokia copyright", #7 - "Incomplete copyright", #8 - "OK", #9 - "OK (Non-Nokia)", #10 - "Multiple license" #11 - ); -use constant VERI_MISSING_FILE => 0; -use constant VERI_MISSING_ID => 1; -use constant VERI_MISSING_HEADER => 2; -use constant VERI_PROPER_COPYRIGHT => 3; -use constant VERI_ID_HEADER_MISMATCH => 4; -use constant VERI_INTERNAL_TO_SF => 5; -use constant VERI_OLD_NOKIA_HEADER => 6; -use constant VERI_UNCLEAR_COPYR => 7; -use constant VERI_INCOMPLETE_COPYR => 8; -use constant VERI_OK => 9; -use constant VERI_OK_NON_NOKIA => 10; -use constant VERI_MULTIPLE_LICENSES => 11; - - -################################## -# Callback for the find function -# (wanted) -# Note ! "no_chdir" not used -################################## -sub process_file -{ - - my $full_filename = $File::Find::name; # Full name needed for result and logs ! - $full_filename =~ s/\\/\//g; # Standardize name - my $filename = $_; # This in filename in the current working directory ! - - #Skip all directory entries - return if -d; - - if ($ignorefilepattern && $full_filename =~ m/$ignorefilepattern/i) - { - printLog(LOG_DEBUG, "File ignored by pattern: ". $full_filename . "\n"); - $ignoreCount++; - return; - } - - # Set initial value from options, turn off later if needed - my $modify = $optModify; - my $willmodify = 1; # For statistics only - - #skip non-source code files - my ($name, $path, $suffix)=fileparse($_, qr/\.[^.]*/); - - my $match = grep {$_ eq lc($suffix)} @extlist; - if (!$match) - { - printLog(LOG_DEBUG, "File ignored: ". $full_filename . "\n"); - $ignoreCount++; - return; - } - - # As there have been cased where e.g. .pkg file has been saved as Unicode format - # Check that we can really modify file (e.g. Unicode files not supported) - if (! (-T $filename)) # Text file only ! - { - printLog(LOG_WARNING, "File not in text format: $full_filename\n"); - return; - } - - - printLog(LOG_DEBUG, "Handling ". $full_filename . "\n"); - - local($/, *FH); - - # Open file for reading here, re-open later if modified - open(FH, "<$filename") or return printLog(LOG_ERROR, "Failed to open file for reading: $full_filename\n"); - - my $filecontent = ; # read whole content into buffer - # Standardize the new-line handling in files by replacing \r with \n - # Some files may be using only \r and it causes problems - $filecontent =~ s/\r/\n/g; - - my $modifiedFilecontent; - my $description = ""; - my $contributors = ""; - - #comment mark - my $cm = '\*'; - my $cm2 = '*'; - my $newheader = ""; - my $oldheader = ""; - my $oldheader2; - my $header_regexp = ""; - my $header_regexp2; - my $isCcomment = 0; - my $isCPPcomment = 0; - my $oldCopyrightYear; - my $matchPos1; - my $matchPos2; - my $unrecog=0; - - - # For statisctics.... - $fileCount++; - - ################### - # Prepare regular expressions - # based on file extensions - ################### - - if (lc($suffix) eq ".s60") - { - # - # Alter exisring distribution policy file - # - my $stat = LICENSE_NONE; - $stat = &handleDistributionValue(\$filecontent, $full_filename); - if ($stat eq LICENSE_CHANGED) - { - $willModifiedFileCount++; - if ($modify) - { - close(FH); # Close null - writeFile(\$filecontent, $filename, $full_filename); - } - } - return; # All done - } - - elsif ( (lc($suffix) eq ".mk" ) or - (lc($suffix) eq ".pl") or (lc($suffix) eq ".py") or (lc($suffix) eq ".pm") or # script - (lc($suffix) eq ".pro") or (lc($suffix) eq ".pri") or # Qt specific - (lc($suffix) eq ".mrp") ) - { - # Makefile, Perl or Python script (# comment) - $cm = '#'; - $cm2 = '#'; - $newheader = &headerOf(OTHER_HEADER()); - $header_regexp = $header_regexps[COMMENT_PERL]; - } - elsif ((lc($suffix) eq ".bat" ) or (lc($suffix) eq ".cmd" )) - { - # Windows command script (@rem comment) - $cm = '@rem'; - $cm2 = '@rem'; - $newheader = &headerOf(OTHER_HEADER()); - $newheader =~ s/\#/\@rem/g; # use rem as comment start, not # - #$newheader = "\@echo off\n" . $newheader; # Disable std output, otherwise rem statements are shown - #$newheader = $newheader . "\@echo on\n"; # Enable std output - $header_regexp = $header_regexps[COMMENT_CMD]; - } - elsif (lc($suffix) eq ".pkg" or lc($suffix) eq ".asm") - { - # SIS package file or Assembly file (; comment) - $cm = ';'; - $cm2 = ';'; - $newheader = &headerOf(OTHER_HEADER()); - $newheader =~ s/\#/\;/g; # use ; as comment start - $header_regexp = $header_regexps[COMMENT_SIS_ASM]; - } - elsif (lc($suffix) eq ".s") - { - # Not all .s files are assemby files !!! - # - if ($filecontent =~ m/\#include\s*\"armasmdef\.h\"/s) - { - # ARM assembly file (C comment) - $newheader = &headerOf(CPP_HEADER()); - # Match both C and C++ comment syntaxes - $isCcomment = 1; - $header_regexp = $header_regexps[COMMENT_C]; - $header_regexp2 = $header_regexps[COMMENT_CPP]; # Use without /s in regexp eval ! - } - elsif ($filecontent =~ m/[\s\t]+AREA[\s\t]+/s) # AREA statement - { - # RVCT assembly file (; comment) - $cm = ';'; - $cm2 = ';'; - $newheader = &headerOf(OTHER_HEADER()); - $newheader =~ s/\#/\;/g; # use ; as comment start - $header_regexp = $header_regexps[COMMENT_SIS_ASM]; - } - else - { - # Not recognized - $unrecog = 1; - printLog(LOG_WARNING, "Assembly file content not recognized, ignored ". $full_filename . "\n"); - } - } - elsif (lc($suffix) eq ".script" ) - { - # Test scipt (// comment) - $cm = '//'; - $cm2 = '//'; - $newheader = &headerOf(OTHER_HEADER()); - $newheader =~ s/\#/\/\//g; # use // as comment start - $header_regexp = $header_regexps[COMMENT_SCRIPT]; - } - else - { - # C/C++ syntaxed file - $newheader = &headerOf(CPP_HEADER()); - # Match both C and C++ comment syntaxes - $isCcomment = 1; - $header_regexp = $header_regexps[COMMENT_C]; - $header_regexp2 = $header_regexps[COMMENT_CPP]; # Use without /s in regexp eval ! - } - - if ($unrecog) - { - close(FH); - $unrecogCount++; - return; - } - - ################### - # Pick up old header in the very first comment block. - # If the actual license text is in the later comment block, it may generate - # UNCLEAR COPYRIGHT CASE (See Consistency checks) - ################### - # - if ($header_regexp2) - { - if ($filecontent =~ m/$header_regexp2/) # Note /s not used by purpose ! - { - $oldheader = $&; - $oldheader2 = $&; - $matchPos2 = $-[0]; - $isCPPcomment = 1; - printLog(LOG_DEBUG, "Orig C++ header:$matchPos2=($oldheader)\n"); - } - } - - if ($filecontent =~ m/$header_regexp/s) - { - $oldheader = $&; - $matchPos1 = $-[0]; - $isCPPcomment = 0; - if ($oldheader2 && ($matchPos2 < $matchPos1)) - { - $oldheader = $oldheader2; # C++ header was earlier - $isCPPcomment = 1; # revert back - } - else - { - printLog(LOG_DEBUG, "Orig C or other header:$header_regexp,$matchPos1\n"); - printLog(LOG_DEBUG, "Orig C or other header:($oldheader)\n"); - } - } - - # - ################### - # Process old header - ################### - - # Handle -verify option - if ($optVerify) - { - if ($optLgpl) - { - &handleVerifyLgpl(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir); - } - elsif ($optEpl) - { - &handleVerifyEpl(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir); - } - else - { - &handleVerify(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir); - } - - close(FH); - return; # All done - } - - # - # Try switch license from SFL to EPL / S60-OEM release - # - my $switchStat = LICENSE_NONE; - $switchStat = &switchLicense(\$filecontent, \$oldheader, $cm, $full_filename, $isCPPcomment); - if ($switchStat eq LICENSE_CHANGED) - { - # OK the switch was sucessful - $willModifiedFileCount++; - if ($modify) - { - close(FH); - writeFile(\$filecontent, $filename, $full_filename); - } - close(FH); - return; # All done - } - elsif ($switchStat eq LICENSE_NOT_SUPPORTED) - { - close(FH); - return; # No worth continue - } - - - # Otherwise (error or no license) continue to create new header - - ################### - # Consistency checks - ################### - if ( (!($oldheader =~ m/$CopyrPattern/is)) && ($filecontent =~ m/$BeginLicenseBlockPattern/s)) - { - # Looks like header is something weired going on. First comment block contains no copyright, - # and still there is "BEGIN LICENSE" block in the file - $UnclearCopyrCount++; - printLog(LOG_INFO, "Non-Nokia copyright (#1) ". $full_filename . "\n"); - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright $sep$sep"."BEGIN LICENSE BLOCK$sep$full_filename$sep$linenumtext\n"); - close(FH); - return; - } - - # - # Switch license from S60 to SFL/EPL according to options - # - - my $otherCopyr = 0; - my $noCopyr = 0; - my $ExternalToNokiaCopyr = 0; - my $s60header = 0; - - # First remove all "Nokia copyright" texts + weired "Copyright known-words" from header - # This because, the header can contain both Nokia and other company copyright statements - my $testheader = makeTestHeader(\$oldheader, 0, REMOVE_SYMBIAN); - printLog(LOG_DEBUG, "Cleaned header=($testheader)\n"); - - # Now test whether it contain non-Nokia (=Nokia+Symbian) copyright statements - # The rule is: If this hits, do not touch the header - - if ($testheader =~ m/$NonNokiaCopyrPattern/is) - { - # Some other than Nokia & Symbian copyright exist in header - $otherCopyr = 1; - $modify = 0; # !!! Do not modify file !!! - $willmodify = 0; - $otherCopyrCount++; - my $failReason = ""; - if (!checkPortionsCopyright(\$oldheader, 0, \$failReason)) - { - printLog(LOG_WARNING, "Non-Nokia copyright (#2) ". $full_filename . "\n"); - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$sep$sep$sep$full_filename$sep$linenumtext\n"); - } - else - { - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep$sep$sep$full_filename$sep$linenumtext\n"); - printLog(LOG_INFO, "Non-Nokia (portions Nokia) copyright ". $full_filename . "\n"); - } - - close(FH); - return; # Quit - } - - # Test header has Nokia or Symbian copyright statement or it could be some other comment - # Check the rest of file - my $wholefile = makeTestHeader(\$filecontent, 1, REMOVE_SYMBIAN); # Check the rest of file - if ($wholefile =~ m/$NonNokiaCopyrPattern/is) - { - # The header might be empty due to weired file header style. - # Check the whole file content, it could be non-nokia file? - $modify = 0; # !!! Do not modify file !!! - $willmodify = 0; - my $failReason = ""; - if (!checkPortionsCopyright(\$filecontent, 1, \$failReason)) - { - $UnclearCopyrCount++; - printLog(LOG_INFO, "Non-Nokia copyright (#2) ". $full_filename . "\n"); - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$failReason$sep$sep$sep$full_filename$sep$linenumtext\n"); - } - else - { - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep$sep$sep$full_filename$sep$linenumtext\n"); - printLog(LOG_INFO, "Non-Nokia (portions Nokia) copyright ". $full_filename . "\n"); - } - close(FH); - return; # Quit - } - - # Check if header is already OK. - # This is needed to keep Ex-Symbian C++ comment syntaxes. - # Also, this avoid unncessary changes in headers. - # NOTE ! If header need to be converted to a new format the check must return FALSE !!! - my $license = licenceIdForOption(); - if (checkHeader(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir, \$license)) - { - if (!checkNoMultipleLicenses(\$filecontent, \$oldheader, $cm, $full_filename, $File::Find::dir)) - { - printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$full_filename$sep" ."1\n"); - printLog(LOG_ERROR, "Multiple licenses:". $full_filename . "\n"); - close(FH); - return; # Failed - } - else - { - # Quit here, header OK - printLog(LOG_INFO, "Header already OK ($license): $full_filename\n"); - close(FH); - return; # Quit - } - } - - # Check if Ex-Symbian file - my $testheader = makeTestHeader(\$oldheader, 0, KEEP_SYMBIAN); - if ($testheader =~ m/$ExternalToNokiaCopyrPattern/is) - { - # External copyright moved to Nokia - my $txt = $1; - $txt =~ s/,//; - $ExternalToNokiaCopyr = 1; - $ExternalToNokiaCopyrCount++; - if ($isCPPcomment) - { - # Normalize the C++ header syntax back to C comment - $modifiedFilecontent = &normalizeCppComment($header_regexp2,$filecontent, \$oldheader); - printLog(LOG_DEBUG, "Normalized External header=($oldheader)\n"); - } - if ($testheader =~ /$copyrYearPattern/) - { - if ($& =~ /$copyrYearPattern2/) - { - $oldCopyrightYear = $&; - } - printLog(LOG_DEBUG, "Old copyright=($oldCopyrightYear)\n"); - } - printLog(LOG_INFO, "Copyright will be converted to Nokia: $full_filename\n"); - printResult(HEADER_CONTEXT() . "$sep"."Converted copyright$sep$sep$sep$full_filename$sep$linenumtext\n"); - } - - elsif ($oldheader =~ m/$NokiaCopyrPattern/is) - { - # Consider it to be Nokia copyright - $s60header = 1; - $NokiaCopyrCount++; - printLog(LOG_DEBUG, "Nokia header=($full_filename)\n"); - if ($isCPPcomment) - { - # Normalize the C++ header syntax back to C comment - $modifiedFilecontent = &normalizeCppComment($header_regexp2, $filecontent, \$oldheader); - printLog(LOG_DEBUG, "Normalized Nokia header=($oldheader)\n"); - } - if ($oldheader =~ /$copyrYearPattern/) - { - if ($& =~ /$copyrYearPattern2/) - { - $oldCopyrightYear = $&; - } - printLog(LOG_DEBUG, "Old copyright2=($oldCopyrightYear)\n"); - } - } - elsif (! ($testheader =~ m/$CopyrPattern/is) ) - { - # No copyright in the header. - $NoCopyrCount++; - $noCopyr = 1; - # printResult(HEADER_CONTEXT() . "$sep"."No Copyright$sep$sep$sep$full_filename$sep$linenumtext\n"); - } - else - { - $UnclearCopyrCount++; - $modify = 0; # !!! Do not modify file !!! - $willmodify = 0; - printLog(LOG_ERROR, "UNCLEAR copyright ". $full_filename . "\n"); - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR COPYRIGHT CASE$sep$sep$sep$full_filename$sep$linenumtext\n"); - } - - - # Get description from current header - if ($oldheader =~ m/$cm\s*Description\s*\:(.*?)$cm\s*(Version)/s) - { - # Description followed by Version - $description = $1; - printLog(LOG_DEBUG, "Old description followed by version ($description)\n"); - } else - { - # Description without Version - # ORIG if ($oldheader =~ m/$cm?\s*Description\s*\:(.*?)$cm\s*(\n)/s) - if ($oldheader =~ m/$cm?\s*Description\s*\:(.*?)($cm|$cm\/|\n)\s*\n/s) - { - $description = $1; - printLog(LOG_DEBUG, "Old description not followed by version ($description)\n"); - } - } - - if ($isCcomment) - { - $description =~ s/\/\*.*//; # Remove possible /* - $description =~ s/\*\/.*//; # Remove possible */ - $description =~ s/\=//g; # Remove possible =/ - } - - # Get contributors from old header - if ( $oldheader =~ m/$cm\s*Contributors\s*\:(.*?)$cm\s*Description\s*\:/s) - { - $contributors = $1; - printLog(LOG_DEBUG, "Old contributors ($contributors)\n"); - } - - # Keep description text - if($description) - { - $newheader =~ s/Description:[ \t]*\n/Description: $description/s; - } - - - #Keep contributor list - if ($contributors) - { - $newheader =~ s/$cm[ \t]*Contributors:[ \t]*\n$cm[ \t]*\n/$cm2 Contributors:$contributors/s; - } - - - ################### - # Modify the header - ################### - if($oldheader) - { - { - # Update the old header to new one - # Old header may be just a description comment, e.g. in script - # - - if ($otherCopyr) - { - # Other copyright statement, do not touch ! - printLog(LOG_DEBUG, "Non-Nokia file not modified: $full_filename\n"); - } - elsif ($noCopyr) - { - - # No copyright statement - if (!isGeneratedHeader(\$oldheader)) - { - # Just add new header - $filecontent = $newheader . $filecontent; - printLog(LOG_INFO, "New header will be added: $full_filename\n"); - } - else - { - printLog(LOG_INFO, "Generated file ignored: $full_filename\n"); - } - } - else - { - # Replace the old external / S60 header - my $newHeaderCopyrYear; - if ($newheader =~ /$copyrYearPattern2/) - { - # This is picked up from newheader template in this script, so should work always ! - $newHeaderCopyrYear = $&; # Pick up year from new header - printLog(LOG_DEBUG, "Template header copyright=($newHeaderCopyrYear)\n"); - } - if (!$newHeaderCopyrYear) - { - # Anyway, some weired error happended - $newHeaderCopyrYear = DEFCOPYRIGHTYEAR; - } - - # Create new copyright years - if ($oldCopyrightYear && !($oldCopyrightYear =~ /$newHeaderCopyrYear/)) - { - # Keep the old copyright !!! - # !!! If adding new copyright year to old header, uncomment the next line !!! - # $oldCopyrightYear .= ",$newHeaderCopyrYear"; - } - if (!$oldCopyrightYear) - { - # Nothing found - $oldCopyrightYear = $newHeaderCopyrYear; - } - printLog(LOG_DEBUG, "New header copyright:$oldCopyrightYear\n"); - $newheader =~ s/$newHeaderCopyrYear/$oldCopyrightYear/; - printLog(LOG_DEBUG, "New header:$full_filename,($newheader)\n"); - if ($modifiedFilecontent) - { - $filecontent = $modifiedFilecontent; # Use the already modified content as basis - } - - # - # SET THE NEW HEADER - # - if (!($filecontent =~ s/$header_regexp/$newheader/s)) - { - printLog(LOG_ERROR, "FAILED to change file header: ". $full_filename . "\n"); - $LicenseChangeErrors++; - $modify = 0; # Can not modify on failure - $willmodify = 0; - } - else - { - printLog(LOG_INFO, "File header will be changed: $full_filename\n"); - } - } - } - } - else - { - if (!isGeneratedHeader(\$filecontent)) # Ensure file is not generated - { - # Missing old header, add new header as such - printLog(LOG_INFO, "Missing header will be added: $full_filename\n"); - $filecontent = $newheader."\n".$filecontent; - } - else - { - printLog(LOG_INFO, "Generated file ignored: $full_filename\n"); - } - } - - if ($description =~ m/^\s*$/g || $description =~ m/$descrTemplateOnly/) - { - $noDescrcount++; - if ($optDescription) - { - printResult(HEADER_CONTEXT() . "$sep"."Description missing$sep$sep$sep$full_filename$sep$linenumtext\n"); - } - } - - close(FH); - - if ($modify) - { - # Re-open the file for modifications - chmod 0777, $filename if !-w; # remove first R/O - open(FH, "+<$filename") or return printLog(LOG_ERROR, "Failed to open file for modifying: $full_filename\n"); - print FH $filecontent or printLog(LOG_ERROR, "Failed to modify file: $full_filename\n"); - truncate(FH, tell(FH)); - $modifiedFileCount++; - close(FH); - } - - if ($willmodify) - { - # Only for statistics - $willModifiedFileCount++; - } - -} - - - -################################## -# Callback for the find function -# (postprocess) -# Note ! "no_chdir" not used -################################## -sub postprocess -{ - my $dir = $File::Find::dir; - printLog(LOG_DEBUG, "postprocess $dir\n"); - - return if (-e DISTRIBUTION_FILENAME); # Already exists ? - - my $full_filename = $dir . "/" . DISTRIBUTION_FILENAME; # Full name needed for results and log - my $filename = DISTRIBUTION_FILENAME; - - if ($ignorefilepattern && $full_filename =~ m/$ignorefilepattern/i) - { - printLog(LOG_DEBUG, "Missing file ignored by pattern: ". $full_filename . "\n"); - $ignoreCount++; - return; - } - - my $filecontent = ""; - my $stat = LICENSE_NONE; - $stat = &handleDistributionValue(\$filecontent, $full_filename); - if ($stat eq LICENSE_CHANGED && $optCreate && isDirectoryNonEmpty('.')) - { - # Create new distribution file to non-empty directory - printResult(DISTRIBUTION_CONTEXT() . "$sep"."New file$sep$sep$sep$full_filename$sep$linenumtext\n"); - if ($optModify) - { - # Without -modify it is possible to see what new files will created - createAndWriteFile(\$filecontent, $filename, $full_filename); - } - $createCount++; # For statistics - } - - -} - - -################################## -# Callback for the find function -# (preprocess). Used by option -verify -# Note ! "no_chdir" not used -################################## -sub preprocess -{ - my $dir = $File::Find::dir; - printLog(LOG_DEBUG, "preprocess $dir\n"); - $lastDistributionValue = ""; # Empty first - - if (!isDirectoryNonEmpty('.')) - { - # Ignore empty dirs - return @_; # Return input args - } - if (!$optVerify) - { - return @_; # Return input args - } - - # - # Currently option -verify required !!! - # - - my $full_filename = $dir . "/" . DISTRIBUTION_FILENAME; # Full name needed for results and log - $full_filename =~ s/\\/\//g; # Standardize name - - my $filename = DISTRIBUTION_FILENAME; - if ($ignorefilepattern && $full_filename =~ m/$ignorefilepattern/i) - { - if (! ($dir =~ m/$INTERNAL/i) ) - { - return @_; - } - } - - # Check existency of the file - if (!open(FH, "<$filename")) - { - printResult(DISTRIBUTION_CONTEXT() . "$sep"."Distribution policy file missing$sep$sep$sep$full_filename$sep$linenumtext\n"); - $verifyFailedCount[VERI_MISSING_FILE]++; - return @_; # Return input args - } - - my $content = ; # IF CONTENT CHECKS - close FH; - - $content =~ s/\n//g; # Remove all new-lines - $content =~ s/^\s+//g; # trim left - $content =~ s/\s+$//g; # trim right - $lastDistributionValue = $content; # Save to global variable for the sub handleVerify - - printLog(LOG_DEBUG, "$full_filename content=$content\n"); - - if ($dir =~ m/$INTERNAL/i) - { - my $isSFId = &isSFDistribution($content); - if ( $isSFId ) - { - # Internal directory has SF distribution value, something is wrong ! - my $comment = ""; # Leave it just empty - printResult(DISTRIBUTION_CONTEXT() . "$sep"."Internal directory going to SF (current value $content)$sep$comment$sep$sep$full_filename$sep$linenumtext\n"); - $verifyFailedCount[VERI_INTERNAL_TO_SF]++; - } - } - elsif (! (($content eq SFL_DISTRIBUTION_VALUE) || ($content eq EPL_DISTRIBUTION_VALUE))) - { - # Neither SFL nor EPL value - my $comment = getCommentText($content,0,"0,3,7,950", $full_filename); - my $isSFId = &isSFDistribution($content); - if (!$isSFId) - { - printResult(DISTRIBUTION_CONTEXT() . "$sep"."SFL or EPL value missing (current value $content)$sep$comment$sep$sep$full_filename$sep$linenumtext\n"); - $verifyFailedCount[VERI_MISSING_ID]++; - } - } - - return @_; # Return input args - -} - -################################################## -# Read distribution file from given directory -################################################## -sub readDistributionValue -{ - - my $dir = shift; - - my $filename = DISTRIBUTION_FILENAME; - my $content = ""; - - if (open(FH, "<$filename")) - { - $content = ; - close FH; - } - - $content =~ s/\n//g; # Remove all new-lines - $content =~ s/^\s+//g; # trim left - $content =~ s/\s+$//g; # trim right - - return $content; -} - - -################################################## -# Make test header from given input text -################################################## -sub makeTestHeader -{ - my $ref = shift; # Input text reference - my $isWholeFile = shift; # $ref is the file content - my $removeExternalToNokia = shift; # Remove to Nokia transferreable copyright texts - - my $tstheader = ""; - - if (!$isWholeFile) - { - $tstheader = $$ref; - } - else - { - # To optimize, whole file == 10k !!! - # The proper header should be included in that amount of data. - $tstheader = substr($$ref, 0, 10*1024); - } - $tstheader =~ s/$NokiaCopyrPattern//gi; - $tstheader =~ s/$PortionsNokiaCopyrPattern//gi; - $tstheader =~ s/$RemoveS60TextBlockPattern//si; - if ($removeExternalToNokia) - { - $tstheader =~ s/$ExternalToNokiaCopyrPattern//gi; - $tstheader =~ s/$PortionsSymbianCopyrPattern//gi; - } - - # Take out special texts containing copyright word - $tstheader =~ s/Copyright\s*\(c\)\s*\.//gi; - $tstheader =~ s/COPYRIGHT[\s\n\*\#+;]*(HOLDER|OWNER|notice)//gi; - - return $tstheader; -} - - -################################################## -# Check whether portions copyright is OK -# Call this for non Nokia cases only ! -################################################## -sub checkPortionsCopyright -{ - my $ref = shift; # Input text reference - my $isWholeFile = shift; # $ref is the file content - my $failReason_ref = shift; # check failure reason (OUT) - - my $tstheader = ""; - - if (!$isWholeFile) - { - $tstheader = $$ref; - } - else - { - # The portions info should be included within first 10 Kb of file - $tstheader = substr($$ref, 0, 10*1024); - } - - if ($tstheader =~ m/$PortionsSymbianCopyrPattern/is) - { - # Symbian portions copyright should be converted to Nokia one - if (!($tstheader =~ m/$PortionsNokiaCopyrPattern/is)) - { - $$failReason_ref = "(portions Symbian copyright)"; - } - else - { - $$failReason_ref = "(portions Nokia+Symbian copyright)"; - } - return 0; - } - - if (!($tstheader =~ m/$NewPortionsNokiaCopyrPattern/is)) - { - # No portions copyright present - $$failReason_ref = ""; - return 0; - } - - return 1; # Should be OK -} - - -################################################## -# Get comment text by ID or filename -# Returns currently empty or value of the $IGNORE -################################################## -sub getCommentText -{ - my $distributionValue = shift; - my $contains = shift; - my $pattern = shift; - my $fullfilename = shift; - - if ($contains) - { - if ($pattern =~ m/$distributionValue/) - { - return $IGNORE; - } - } - else - { - # Not contains - if (!($pattern =~ m/$distributionValue/)) - { - return $IGNORE; - } - } - - my $ignoreThis = $manualIgnoreFileHash{lc($fullfilename)}; - if (defined $ignoreThis) - { - printLog(LOG_DEBUG, "$IGNORE_MAN 2: $fullfilename\n"); - return $IGNORE_MAN; - } - - return ""; -} - - -################################################## -# Write content to file -################################################## -sub writeFile -{ - my $filecontent_ref = shift; - my $filename = shift; - my $full_filename = shift; - - my $fh; - - chmod 0777, $filename if !-w; # remove first R/O - open($fh, "+<$filename") or return printLog(LOG_ERROR, "Failed to open file for modifying: $full_filename\n"); - print $fh $$filecontent_ref or printLog(LOG_ERROR, "Failed to modify file: $full_filename\n"); - truncate($fh, tell($fh)); - close($fh); - - $modifiedFileCount++; -} - -################################################## -# Create file and write content to file -################################################## -sub createAndWriteFile -{ - my $filecontent_ref = shift; - my $filename = shift; - my $full_filename = shift; - - my $fh; - - open($fh, ">$filename") or return printLog(LOG_ERROR, "Failed to create file: $full_filename\n"); - print $fh $$filecontent_ref or printLog(LOG_ERROR, "Failed to write file: $full_filename\n"); - close($fh); -} - -################################## -# Check if current directory is empty -################################## -sub isDirectoryNonEmpty -{ - my ($dir) = @_; - opendir (DIR,$dir) or printLog(LOG_ERROR, "Can't opendir $dir\n"); - for(readdir DIR) - { - if (-f $_) - { - closedir DIR; - return 1; - }; - } - closedir DIR; - return 0; -} - - -################################################## -# Change SFL back to S60, or -# Change SFl to EPL -# Returns LICENSE_CHANGED if function switched the license succesfully -################################################## -# Switch only license text and URL -my $sflText = '"Symbian Foundation License v1.0"'; -my $sflTextPattern = '(the\s*License\s*)?\"Symbian\s*Foundation\s*License\s*v1\.0\"'; -my $sflUrlPattern = 'http\:\/\/www\.symbianfoundation\.org\/legal\/sfl\-v10\.html'; -my $sflUrl = 'http://www.symbianfoundation.org/legal/sfl-v10.html'; -my $eplText = '"Eclipse Public License v1.0"'; -my $eplUrl = 'http://www.eclipse.org/legal/epl-v10.html'; -my $eplUrlPattern = 'http\:\/\/www\.eclipse\.org\/legal\/epl\-v10\.html'; -my $eplTextPattern = '"Eclipse\s*Public\s*License\s*v1\.0"'; -my $oldEplTextPattern = 'the\s*License\s*"Eclipse\s*Public\s*License\s*v1\.0"'; # "the License" is unncessary - -sub switchLicense -{ - my $filecontent_ref = shift; - my $header_ref = shift; - my $commentChar = shift; - my $fullfilename = shift; - my $isCPPcomment = shift; - - my $testValueSfl = ""; - my $testValueEpl = ""; - my $testValueS60 = ""; - - if ($isCPPcomment) - { - # xSymbian files use this style - $commentChar = '//'; - # in xSymbian files there are comments like, /// some text - $$filecontent_ref =~ s/(\/){3,}/\/\//g; # replace ///+ back to // - } - - - # In from value \* need to be escaped. - my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl); - my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl); - - $commentChar =~ s/\\//; # Remove \ from possible \* - my $ToS60Text = &partialHeaderOf(S60_LICENSE,$commentChar, \$testValueS60); - - # Note that partial headers are manually quoted in the declaration - # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones - # because plain text contains special chars, like . - - printLog(LOG_DEBUG, "switchLicense: $fullfilename, $testValueEpl\n"); - - if ($$filecontent_ref =~ m/$testValueSfl/s) - { - # SFL license - - if ($optOem) - { - # Switch from SFL to S60 - if (!($$filecontent_ref =~ s/$FromSFLText/$ToS60Text/s)) - { - printLog(LOG_ERROR, "FAILED to change SFL license to S60: ". $fullfilename . "\n"); - $LicenseChangeErrors++; - return LICENSE_ERROR; - } - printLog(LOG_WARNING, "License will be swicthed from SFL to S60: ". $fullfilename . "\n"); - $SflToS60Changes++; - return LICENSE_CHANGED; - } - elsif ($optEpl) - { - # Switch from SFL to EPL - if (! ( ($$filecontent_ref =~ s/$sflTextPattern/$eplText/s) && ($$filecontent_ref =~ s/$sflUrlPattern/$eplUrl/s) ) ) - { - printLog(LOG_ERROR, "FAILED to change SFL to EPL: ". $fullfilename . "\n"); - $LicenseChangeErrors++; - return LICENSE_ERROR; - } - else - { - printLog(LOG_INFO, "License will be switched from SFL to EPL: ". $fullfilename . "\n"); - } - $SflToEplChanges++; - return LICENSE_CHANGED; - } - } - - if ($$filecontent_ref =~ m/$testValueEpl/s) - { - if ($optOem) - { - printLog(LOG_ERROR, "Not supported to change EPL to S60: ". $fullfilename . "\n"); - return LICENSE_NOT_SUPPORTED; - } - elsif (!$optEpl) - { - # Switch from EPL to SFL - if (! ( ($$filecontent_ref =~ s/$eplTextPattern/$sflText/s) && ($$filecontent_ref =~ s/$eplUrlPattern/$sflUrl/s) ) ) - { - printLog(LOG_ERROR, "FAILED to change EPL to SFL: ". $fullfilename . "\n"); - $LicenseChangeErrors++; - return LICENSE_ERROR; - } - else - { - printLog(LOG_WARNING, "License will be switched from EPL to SFL: ". $fullfilename . "\n"); - } - $EplToSflChanges++; - return LICENSE_CHANGED; - } - - # EPL text cleanup (remove unncessary "the License") - if ($$filecontent_ref =~ m/$oldEplTextPattern/s) - { - # EPL header contains extra words, get rid of them (allow script replace old header) - if ($$filecontent_ref =~ s/$oldEplTextPattern/$eplText/s) - { - # Not error if fails - printLog(LOG_INFO, "Unnecessary \"the License\" will be removed: $fullfilename\n"); - return LICENSE_CHANGED; - } - } - - } - else - { - return LICENSE_NONE; # Allow caller decide - } - -} - -################################################## -# Verify changes -################################################## -sub handleVerify -{ - my $filecontent_ref = shift; - my $header_ref = shift; - my $commentChar = shift; - my $fullfilename = shift; - my $directory = shift; - - my $testValueSfl = ""; - my $testValueEpl = ""; - my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl); - my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl); - - if ($lastDistributionValue eq "") - { - # Distribution file may be empty if giving single file as input - # Read it - $lastDistributionValue = readDistributionValue($directory); - } - - printLog(LOG_DEBUG, "handleVerify $fullfilename, $$header_ref\n"); - - # First check Non-Nokia copyright files - my $testheader = makeTestHeader($header_ref, 0, REMOVE_SYMBIAN); - if (($testheader =~ m/$NonNokiaCopyrPattern/is)) - { - printLog(LOG_DEBUG, "DEBUG:Extra check1 $&\n"); - if (!($testheader =~ m/$ExternalToNokiaCopyrPattern/si)) - { - # Non-nokia file - if ($testheader =~ m/$copyrYearPattern/si) - { - # Looks like copyright statement - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $otherCopyrCount++; - $verifyFailedCount[VERI_OK_NON_NOKIA]++; - return 1; # OK - } - else - { - # Incomplete copyright ? - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia incomplete copyright$sep" . "$IGNORE?$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_OK]++; - return 0; - } - } - } - - # The header might be empty due to weired file header style. - # Check the whole file content, it could be non-nokia file? - my $filestart = makeTestHeader($filecontent_ref, 1, REMOVE_SYMBIAN); - - if ($filestart =~ m/$NonNokiaCopyrPattern/is) - { - # There is Non-Nokia copyright statement in the file - if (($filestart =~ m/$testValueSfl/is) || ($filestart =~ m/$testValueEpl/is)) - { - # Non-Nokia file, but still SFL or EPL header - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright with SFL/EPL$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_UNCLEAR_COPYR]++; - return 0; - } - elsif ($$filecontent_ref =~ m/$OldNokiaPattern2/is) - { - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Old Nokia copyright$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_OLD_NOKIA_HEADER]++; - return 0; - } - else - { - # Non-Nokia file - my $failReason = ""; - if (!checkPortionsCopyright($filecontent_ref, 1, \$failReason)) - { - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright$failReason$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_UNCLEAR_COPYR]++; - return 0; - } - else - { - # Contains portions copyright - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - return 1; - } - } - } - - # - # OK, it should be Nokia copyrighted file - # - - # Note that partial headers are manually quoted in the declaration - # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones - # because plain text contains special chars, like . - printLog(LOG_DEBUG, "handleVerify testheaders: $testValueSfl,$testValueEpl,$$header_ref\n"); - - if ( !( ($$header_ref =~ m/$testValueSfl/s) || ($$header_ref =~ m/$testValueEpl/s) || - ($$filecontent_ref =~ m/$testValueSfl/s) || ($$filecontent_ref =~ m/$testValueEpl/s) - ) ) - { - # Header not found from header or whole file - if (isGeneratedHeader($header_ref) || isGeneratedHeader($filecontent_ref)) - { - # OK, it is generated header - if ($optOutputOK) - { - printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "Generated header$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_OK]++; - return 1; # OK - } - - my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename); - if (($$header_ref =~ m/$OldNokiaPattern2/is) || ($$filecontent_ref =~ m/$OldNokiaPattern2/is)) - { - printResult(HEADER_CONTEXT() . "$sep"."SFL or EPL header missing (old Nokia copyright)$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - else - { - printResult(HEADER_CONTEXT() . "$sep"."SFL or EPL header missing$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_MISSING_HEADER]++; - return 0; - } - - # Cross header versus distribution ID - if ($lastDistributionValue ne "") - { - # Also other than 3 or 7 may be OK based on the config file - my $isSFId = &isSFDistribution($lastDistributionValue); - printLog(LOG_DEBUG, "DEBUG:handleVerify:Other ID OK=$isSFId\n"); - if ( (($$header_ref =~ m/$testValueSfl/s) || ($$filecontent_ref =~ m/$testValueSfl/s)) && !$isSFId) - { - my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename); - printResult(HEADER_CONTEXT() . "$sep"."SFL header vs. distribution id ($lastDistributionValue) mismatch$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_ID_HEADER_MISMATCH]++; - return 0; - } - if ( (($$header_ref =~ m/$testValueEpl/s) || ($$filecontent_ref =~ m/$testValueEpl/s)) && !$isSFId ) - { - my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename); - printResult(HEADER_CONTEXT() . "$sep"."EPL header vs. distribution id ($lastDistributionValue) mismatch$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_ID_HEADER_MISMATCH]++; - return 0; - } - } - - if (!checkNoMultipleLicenses($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory)) - { - printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$fullfilename$sep" ."1\n"); - printLog(LOG_ERROR, "Multiple licenses:". $fullfilename . "\n"); - $verifyFailedCount[VERI_MULTIPLE_LICENSES]++; - return 0; # Failed - } - - - # We should have proper header in place - - printLog(LOG_DEBUG, "handleVerify: $$filecontent_ref\n"); - # Check New Nokia copyright pattern (added one sentence to the old one) - if (! (($$header_ref =~ m/$NewNokiaPattern/s) || ($$filecontent_ref =~ m/$NewNokiaPattern/s)) ) - { - my $comment = getCommentText($lastDistributionValue, 0, "0,3,7,950", $fullfilename); - printResult(HEADER_CONTEXT() . "$sep"."Proper Nokia copyright statement missing$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_PROPER_COPYRIGHT]++; - return 0; # Failed - } - - if ($optOutputOK) - { - printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "OK$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_OK]++; - - return 1; - -} - - -################################################## -# Verify changes -################################################## -sub handleVerifyEpl -{ - my $filecontent_ref = shift; - my $header_ref = shift; - my $commentChar = shift; - my $fullfilename = shift; - my $directory = shift; - - my $testValueSfl = ""; - my $testValueEpl = ""; - my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl); - my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl); - - if ($lastDistributionValue eq "") - { - # Distribution file may be empty if giving single file as input - # Read it - $lastDistributionValue = readDistributionValue($directory); - } - - printLog(LOG_DEBUG, "handleVerifyEpl $fullfilename, $$header_ref\n"); - - # First check Non-Nokia copyright files - my $testheader = makeTestHeader($header_ref, 0, REMOVE_SYMBIAN); - if (($testheader =~ m/$NonNokiaCopyrPattern/is)) - { - printLog(LOG_DEBUG, "DEBUG:Extra check1 $&\n"); - if (!($testheader =~ m/$ExternalToNokiaCopyrPattern/si)) - { - # Non-nokia file - if ($testheader =~ m/$copyrYearPattern/si) - { - # Looks like copyright statement - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $otherCopyrCount++; - $verifyFailedCount[VERI_OK_NON_NOKIA]++; - return 1; # OK - } - else - { - # Incomplete copyright ? - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia incomplete copyright$sep" . "$IGNORE?$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_OK]++; - return 0; - } - } - } - - # The header might be empty due to weired file header style. - # Check the whole file content, it could be non-nokia file? - my $filestart = makeTestHeader($filecontent_ref, 1, REMOVE_SYMBIAN); - - if ($filestart =~ m/$NonNokiaCopyrPattern/is) - { - # There is Non-Nokia copyright statement in the file - if ($filestart =~ m/$testValueEpl/is) - { - # Non-Nokia file, but still EPL header - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright with EPL$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_UNCLEAR_COPYR]++; - return 0; - } - elsif ($$filecontent_ref =~ m/$OldNokiaPattern2/is) - { - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Old Nokia copyright$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_OLD_NOKIA_HEADER]++; - return 0; - } - else - { - # Non-Nokia file - my $failReason = ""; - if (!checkPortionsCopyright($filecontent_ref, 1, \$failReason)) - { - printResult(HEADER_CONTEXT() . "$sep"."UNCLEAR Non-Nokia copyright$failReason$sep" . "$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_UNCLEAR_COPYR]++; - return 0; - } - else - { - # Contains portions copyright - printResult(HEADER_CONTEXT() . "$sep"."Non-Nokia (portions Nokia) copyright$sep" . "$IGNORE$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - return 1; - } - } - } - - # - # OK, it should be Nokia copyrighted file - # - - my $isSFId = &isSFDistribution($lastDistributionValue); - - # Note that partial headers are manually quoted in the declaration - # Otherwise \Q$EPLText\E would be needed around those ones - # because plain text contains special chars, like . - printLog(LOG_DEBUG, "handleVerify testheaders: $testValueEpl,$$header_ref\n"); - - if ( !( ($$header_ref =~ m/$testValueEpl/s) || ($$filecontent_ref =~ m/$testValueEpl/s) ) ) - { - # Header not found from header or whole file - if (isGeneratedHeader($header_ref) || isGeneratedHeader($filecontent_ref)) - { - # OK, it is generated header - if ($optOutputOK) - { - printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "Generated header$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_OK]++; - return 1; # OK - } - - if (!$isSFId) - { - return 1; - } - - if (($$header_ref =~ m/$testValueSfl/s) || ($$filecontent_ref =~ m/$testValueSfl/s)) - { - # Still SFL header in place - printResult(HEADER_CONTEXT() . "$sep"."EPL header missing (SFL header used)$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - elsif (($$header_ref =~ m/$OldNokiaPattern2/is) || ($$filecontent_ref =~ m/$OldNokiaPattern2/is)) - { - printResult(HEADER_CONTEXT() . "$sep"."EPL header missing (old Nokia copyright)$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - else - { - printResult(HEADER_CONTEXT() . "$sep"."EPL header missing$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_MISSING_HEADER]++; - return 0; - } - - # Cross header versus distribution ID - if ($isSFId) - { - # Also other than 7 may be OK based on the config file - printLog(LOG_DEBUG, "DEBUG:handleVerify:Other ID OK=$isSFId\n"); - if ( ($$filecontent_ref =~ m/$testValueEpl/s) && ($lastDistributionValue ne EPL_DISTRIBUTION_VALUE) ) - { - printResult(HEADER_CONTEXT() . "$sep"."EPL header vs. distribution id ($lastDistributionValue) mismatch$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_ID_HEADER_MISMATCH]++; - return 0; - } - } - - if (!checkNoMultipleLicenses($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory)) - { - printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$fullfilename$sep" ."1\n"); - printLog(LOG_ERROR, "Multiple licenses:". $fullfilename . "\n"); - $verifyFailedCount[VERI_MULTIPLE_LICENSES]++; - return 0; # Failed - } - - - # We should have proper header in place - - printLog(LOG_DEBUG, "handleVerify: $$filecontent_ref\n"); - # Check New Nokia copyright pattern (added one sentence to the old one) - if (! (($$header_ref =~ m/$NewNokiaPattern/s) || ($$filecontent_ref =~ m/$NewNokiaPattern/s)) ) - { - printResult(HEADER_CONTEXT() . "$sep"."Proper Nokia copyright statement missing$sep$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - $verifyFailedCount[VERI_PROPER_COPYRIGHT]++; - return 0; # Failed - } - - if ($optOutputOK) - { - printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "OK$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_OK]++; - - return 1; - -} - - - -################################################## -# Verify changes for LGPL headers -################################################## -sub handleVerifyLgpl -{ - my $filecontent_ref = shift; - my $header_ref = shift; - my $commentChar = shift; - my $fullfilename = shift; - my $directory = shift; - - my $testValueLgpl = ""; - my $FromLgplText = &partialHeaderOf(LGPL_LICENSE,$commentChar, \$testValueLgpl); - - if ($lastDistributionValue eq "") - { - # Distribution file may be empty if giving single file as input - # Read it - $lastDistributionValue = readDistributionValue($directory); - } - - printLog(LOG_DEBUG, "handleVerifyLgpl $fullfilename, $$header_ref\n"); - - # Note that partial headers are manually quoted in the declaration - # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones - # because plain text contains special chars, like . - printLog(LOG_DEBUG, "handleVerifyLgpl testheaders: $testValueLgpl,$$header_ref\n"); - - if ( !( ($$header_ref =~ m/$testValueLgpl/s) || ($$filecontent_ref =~ m/$testValueLgpl/s) ) ) - { - # Header not found from header or whole file - if (isGeneratedHeader($header_ref) || isGeneratedHeader($filecontent_ref)) - { - # OK, it is generated header - if ($optOutputOK) - { - printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "Generated header$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_OK]++; - return 1; # OK - } - - my $comment = getCommentText($lastDistributionValue, 0, "0,3,7", $fullfilename); - if (($$header_ref =~ m/$OldNokiaPattern2/is) || ($$filecontent_ref =~ m/$OldNokiaPattern2/is)) - { - printResult(HEADER_CONTEXT() . "$sep"."LGPL header missing (old Nokia copyright)$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - else - { - printResult(HEADER_CONTEXT() . "$sep"."LGPL header missing$sep$comment$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - $verifyFailedCount[VERI_MISSING_HEADER]++; - return 0; - } - - if (!checkNoMultipleLicenses($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory)) - { - printResult(HEADER_CONTEXT() . "$sep"."Multiple licenses$sep$sep$sep$fullfilename$sep" ."1\n"); - printLog(LOG_ERROR, "Multiple licenses:". $fullfilename . "\n"); - $verifyFailedCount[VERI_MULTIPLE_LICENSES]++; - return 0; # Failed - } - - - if ($optOutputOK) - { - printResult(HEADER_CONTEXT() . "$sep"."OK$sep" . "OK$sep$lastDistributionValue$sep$fullfilename$sep$linenumtext\n"); - } - - $verifyFailedCount[VERI_OK]++; - - return 1; - -} - - -################################################## -# Test if header is already OK -# NOTE ! If header need to be converted to a new format, the -# check must return FALSE !!! -################################################## -sub checkHeader -{ - my $filecontent_ref = shift; - my $header_ref = shift; - my $commentChar = shift; - my $fullfilename = shift; - my $directory = shift; - my $req_license_ref = shift; # in/out !!! - - my $testValueSfl = ""; - my $testValueEpl = ""; - my $testValueLgpl = ""; - - my $FromSFLText = &partialHeaderOf(SFL_LICENSE,$commentChar, \$testValueSfl); - my $FromEPLText = &partialHeaderOf(EPL_LICENSE,$commentChar, \$testValueEpl); - my $FromLGPLText = &partialHeaderOf(LGPL_LICENSE,$commentChar, \$testValueLgpl); - - # Note that partial headers are manually quoted in the declaration - # Otherwise \Q$SFLText\E and \Q$EPLText\E would be needed around those ones - # because plain text contains special chars, like . - - my $retLicense = SFL_LICENSE; # default - my $testValue = $testValueSfl; - - if ($$req_license_ref == EPL_LICENSE) - { - $testValue = $testValueEpl; - $retLicense = EPL_LICENSE; - } - elsif ($$req_license_ref == LGPL_LICENSE) - { - $testValue = $testValueLgpl; - $retLicense = LGPL_LICENSE; - } - - my $ret = 0; - $ret = ($$header_ref =~ m/$testValue/s); - if (!$ret) - { - # Check the rest of file - $ret = ($$filecontent_ref =~ m/$testValue/s); - } - - printLog(LOG_DEBUG, "checkHeader return=$ret\n"); - - if ($ret) - { - $$req_license_ref = $retLicense; - } - - return $ret; -} - - -################################################## -# Test if file does not contain multiple licenses -# Returns 0 if test failed -################################################## -sub checkNoMultipleLicenses -{ - my $filecontent_ref = shift; - my $header_ref = shift; - my $commentChar = shift; - my $fullfilename = shift; - my $directory = shift; - - my $usedLicense = SFL_LICENSE; - my $licenseCnt = 0; - if (checkHeader($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory, \$usedLicense)) - { - printLog(LOG_DEBUG, "checkNoMultipleLicenses SFL: $fullfilename\n"); - $licenseCnt++; - } - - $usedLicense = EPL_LICENSE; - if (checkHeader($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory, \$usedLicense)) - { - printLog(LOG_DEBUG, "checkNoMultipleLicenses EPL: $fullfilename\n"); - $licenseCnt++; - } - - $usedLicense = LGPL_LICENSE; - if (checkHeader($filecontent_ref, $header_ref, $commentChar, $fullfilename, $directory, \$usedLicense)) - { - printLog(LOG_DEBUG, "checkNoMultipleLicenses LGPL: $fullfilename\n"); - $licenseCnt++; - } - - if ($licenseCnt > 1) - { - return 0; # check failed - } - return 1; -} - -################################################## -# Change distribution value -# Can also be called with empty file content -################################################## -sub handleDistributionValue -{ - my $filecontent_ref = shift; - my $filename = shift; - my $content = $$filecontent_ref; - - if ($optVerify) - { - # Ignored - return LICENSE_NONE; - } - - $content =~ s/\n//g; # Remove all new-lines - $content =~ s/^\s+//g; # trim left - $content =~ s/\s+$//g; # trim right - - if ($content ne "" && $content ne ZERO_DISTRIBUTION_VALUE) - { - if ($optEpl && ($content eq SFL_DISTRIBUTION_VALUE )) - { - # Allow switching SFL to EPL - $$filecontent_ref = EPL_DISTRIBUTION_VALUE; - printLog(LOG_INFO, "Distribution value changed from $content to $$filecontent_ref: $filename\n"); - return LICENSE_CHANGED; - } - else - { - # Otheriwise do not touch non-zero files ! (agreed with build team) - $ignoreCount++; - return LICENSE_NONE; - } - } - - if ($optOem) - { - # Leave existing (or missing) value as it was - return LICENSE_NONE; - } - elsif ($optEpl) - { - $$filecontent_ref = EPL_DISTRIBUTION_VALUE; - printLog(LOG_INFO, "Distribution value changed from $content to $$filecontent_ref: $filename\n"); - return LICENSE_CHANGED; - } - else # SFL - { - $$filecontent_ref = SFL_DISTRIBUTION_VALUE; - printLog(LOG_INFO, "Distribution value changed from $content to $$filecontent_ref: $filename\n"); - return LICENSE_CHANGED; - } - - return LICENSE_NONE; - -} - -################################################## -# Select proper -################################################## -sub licenceIdForOption -{ - if ($optEpl) - { - return EPL_LICENSE; - } - elsif ($optLgpl) - { - return LGPL_LICENSE; - } - else # Must be - { - return SFL_LICENSE; - } -} - - -################################################## -# Select proper header -################################################## -sub headerOf -{ - my $style = shift; - - if ($style < 0 || $style > 1) - { - printLog(LOG_ALWAYS, "INTERNAL ERROR: Header index out of bounds:$style. Exiting.\n"); - exit 1; - } - - my $ref; - if ($optEpl) - { - $ref = $EplHeaders[$style]; - } - elsif ($optLgpl) - { - $ref = $LgplHeaders[$style]; - } - else # SFL - { - $ref = $SflHeaders[$style]; - } - - # Return the actual value - return $$ref; -} - -################################################## -# Select proper partial header -################################################## -sub partialHeaderOf -{ - my $license = shift; - my $commentChar = shift; - my $testValue_ref = shift; - - my $ref; - my $ref2; - if ($license eq EPL_LICENSE) - { - $ref = $EplHeaders[2]; - $ref2 = $EplHeaders[3]; - } - elsif ($license eq S60_LICENSE) - { - $ref = $S60Headers[2]; - $ref2 = $S60Headers[3]; - } - elsif ($license eq LGPL_LICENSE) - { - $ref = $LgplHeaders[2]; - $ref2 = $LgplHeaders[3]; - } - elsif ($license eq SFL_LICENSE) - { - # SFL License - $ref = $SflHeaders[2]; - $ref2 = $SflHeaders[3]; # return value - } - else - { - printLog(LOG_ALWAYS, "INTERNAL ERROR: Invalid license parameter :$license. Exiting.\n"); - exit 1; - } - - # Switch to proper comment char - my $ret = $$ref; - $ret =~ s/$CC/$commentChar/g; # Replace the proper comment starter character - - # Return values - $$testValue_ref = $$ref2; - return $ret; -} - - -################################################## -# Print result line -################################################## -sub normalizeCppComment -{ - my $header_regexp2 = shift; - my $filecontent = shift; - my $oldheader_ref = shift; # in/out - - - # Normalize the C++ header syntax back to C++ in the file content - # in order to standardize stuff later on - $$oldheader_ref =~ s/(\/){3,}/\/\//g; # replace ///+ back to // - $$oldheader_ref =~ s/\/\//*/g; # Replace now // with * - $$oldheader_ref = "/*\n" . $$oldheader_ref . "*/\n"; # Add /* and */ markers - - # Created saved modified file content into memory - # This is the best way to do this. - my $ret = $filecontent; - $ret =~ s/$header_regexp2/$$oldheader_ref/; # Note /s not used by purpose ! - return $ret; -} - - - -################################################## -# Print result line -################################################## -sub printResult -{ - my $text = shift; - - if ($outputfile) - { - print OUTPUT $text; - } - else - { - print $text; - } - - printLog(LOG_DEBUG(), $text); - -} - -################################################## -# Print log line -################################################## -sub printLog -{ - my $loglevel = shift; - my $text = shift; - - if ($loglevel > $optLogLevel) - { - return; # No logging - } - if ($logFile) - { - print LOG $LOGTEXTS[$loglevel] . $text; - } - - return 0; -} - - -################################################## -# Print log line -################################################## -sub printLogStatisticNumber -{ - my $number = shift; - my $loglevel = shift; - my $text = shift; # Should contains %d where to put the number - - if ($number == 0) - { - return; # No logging - } - - if ($text =~ m/\%d/) - { - $text =~ s/\%d/$number/; - } - else - { - # Add number to the beginning of text - $text = $number . " " . $text; - } - - if ($loglevel > $optLogLevel) - { - return; # No logging - } - if ($logFile) - { - print LOG $LOGTEXTS[$loglevel] . $text; - } - - return 0; -} - - -################################################## -# Read the content of old output -################################################## -sub readOldOutput -{ - my($filename) = shift; - my $fh = new FileHandle "<$filename"; - if (!defined($fh)) - { - printLog(LOG_ERROR, "Could not open file $filename for read\n"); - return; - } - - my @lines = <$fh>; - my $line; - foreach $line (@lines) - { - my (@parts) = split(/\,/,$line); # Split line with "," separator - if ($parts[2] =~ m/$IGNORE_MAN/i) - { - my $fullfilename = lc($parts[4]); - $fullfilename =~ s/\\/\//g; # Standardize name - $manualIgnoreFileHash{$fullfilename} = "1" ; # Just some value - printLog(LOG_DEBUG, "Manually ignoring file:$fullfilename\n"); - } - } - - close ($fh); -} - -################################################## -# Read configuation file which has the format: -# sf-update-licence-header-config-1.0 -################################################## -sub readConfig -{ - my ($fname) = @_; - - open(IN,$fname) || die "Unable to open file: \"$fname\" for reading."; - LINE: - while() - { - chomp; - # tr/A-Z/a-z/; # Do not lowercase pattern - my $line = $_; - $line =~ s/^\s+//; # trim left - $line =~ s/\s+$//; # trim right - - next LINE if length($line) == 0; # # Skip empty lines - next LINE if ($line =~ /^\#.*/); # Skip comments; - - if ($line =~ /^sf-update-licence-header-config.*/i) - { - my ($tmp1, $tmp2) = split(/sf-update-licence-header-config-/,$line); # Get version - $configVersion = $tmp2; - } - elsif ($line =~ /^sf-distribution-id/i) - { - my ($tmp, @parts) = split(/[\s\t]+/,$line); # space as separator - my $cnt = @parts; - push(@sfDistributionIdArray, @parts); - my $cnt = @sfDistributionIdArray; - printLog(LOG_DEBUG, "readConfig:sfDistributionIdArray count:$cnt\n"); - } - elsif ($line =~ /^sf-generated-header/i) - { - my ($tmp, @parts) = split(/[\s\t]+/,$line); # space as separator - my $cnt = @parts; - push(@sfGeneratedPatternArray, @parts); - my $cnt = @sfGeneratedPatternArray; - printLog(LOG_DEBUG, "readConfig:sfGeneratedPatternArray count:$cnt\n"); - } - } - - # Pre-compile here the source line pattern - close (IN); -} - - -################################################## -# Test ID is under SF distribution -################################################## -sub isSFDistribution -{ - my $id = shift; - - if (($id == SFL_DISTRIBUTION_VALUE) || ($id == EPL_DISTRIBUTION_VALUE)) - { - # Implicit case - return 1; - } - - my $otherOkId = grep { $_ eq $id } @sfDistributionIdArray; # Use exact match - return $otherOkId; -} - -################################################## -# Test header contains generated file pattern -################################################## -sub isGeneratedHeader -{ - my $header_ref = shift; - - my $count = grep { $$header_ref =~ m/$_/is } @sfGeneratedPatternArray; - return $count; -} - - -################################################## -# MAIN -################################################## - -GetOptions( - 'h|help' => \$help, #print help message - 'm|modify' => \$optModify, #Allow modifications - 'c|create' => \$optCreate, #Create missing file - 'output:s' => \$outputfile, #Output (result) file - 'ignorefile:s' => \$ignorefilepattern, #Ignore file pattern - 'oldoutput:s' => \$oldOutputFile, #Old output file - 'log:s' => \$logFile, # Log file - 'verbose:i' => \$optLogLevel, # Logging level - 'epl' => \$optEpl, # Switch file header to EPL one - 'lgpl' => \$optLgpl, # Switch file header LGPL v2.1 - 'oem' => \$optOem, # Switch back S60 header for OEM release. - 'eula' => \$optOem, # Switch back S60 header for EULA (End-User License Agreement) release. Same as OEM - 'append' => \$optAppend, # Append result files - 'verify' => \$optVerify, # Verifies files has correct header - 'configfile:s' => \$configFile, - 'description!' => \$optDescription, # output missing description - 'okoutput!' => \$optOutputOK # output also OK entries - ); - -die $usage if $#ARGV<0; -die $usage if $help; - -if ($logFile) -{ - my $openmode = ">" . ($optAppend ? ">" : ""); - open (LOG, "$openmode$logFile") || die "Couldn't open $openmode$logFile\n"; # Can not call printLog - LOG->autoflush(1); # Force flush -} - -printLog(LOG_INFO, "========================\n"); - -if ($oldOutputFile && $optVerify) -{ - readOldOutput($oldOutputFile); -} - -if (!$configFile) -{ - $configFile = "$Bin/SFUpdateLicenceHeader.cfg"; -} - -if ($configFile && -e $configFile) -{ - &readConfig($configFile); -} - -if (!$ignorefilepattern) -{ - # Set decent default value - if ($optOem) - { - # Scan through internal stuff all source dirs just in case - $ignorefilepattern = "(_ccmwaid\.inf|\.svn)"; - } - else - { - $ignorefilepattern = "(abld\.bat|_ccmwaid\.inf|\.svn|/docs/|/internal/|/doc/)"; - } -} - -if ($optEpl) -{ - printLog(LOG_INFO, "Option -epl used\n"); -} -if ($optLgpl) -{ - printLog(LOG_INFO, "Option -lgpl used\n"); -} -if ($optOem) -{ - printLog(LOG_INFO, "Option -oem used\n"); - # Modify ignore to contain also internal dirs just in case -} -if ($optModify) -{ - printLog(LOG_INFO, "Option -modify used\n"); -} -if ($optVerify) -{ - printLog(LOG_INFO, "Option -verify used\n"); -} -if ($optCreate) -{ - printLog(LOG_INFO, "Option -create used\n"); -} - -if ($ignorefilepattern) -{ - printLog(LOG_INFO, "Option -ignorefile has value: $ignorefilepattern\n"); -} - -my $startTime = time; - -if ($outputfile) -{ - my $openmode = ">" . ($optAppend ? ">" : ""); - open (OUTPUT, "$openmode$outputfile") || die "Couldn't open $outputfile\n"; - OUTPUT->autoflush(1); # Force flush -} - -if (! -e $ARGV[0] ) -{ - printLog(LOG_ERROR, "$ARGV[0] not found\n"); - if ($logFile) - { - close LOG; - } - exit(1); -} - -printLog(LOG_INFO,"SFUpdateLicenceHeader.pl version " . VERSION . " statistics:\n"); -printLog(LOG_INFO, "Directory/file=@ARGV\n"); - -# -# Process files in the given directory recursively -# -# NOTE : "no_chdir" option not used --> find changes the current working directory -find({ wanted => \&process_file, postprocess => \&postprocess, preprocess => \&preprocess }, @ARGV); - -if ($outputfile) -{ - close OUTPUT; -} - -my $elapsedTime = time - $startTime; - -printLogStatisticNumber($fileCount, LOG_INFO, "%d files checked\n") ; -if ($optModify) -{ - printLogStatisticNumber($modifiedFileCount, LOG_INFO, "%d files modified \n") ; -} -else -{ - printLogStatisticNumber($willModifiedFileCount, LOG_INFO, "%d will be modified \n") ; -} -printLogStatisticNumber($ignoreCount, LOG_INFO, "%d files ignored.\n") ; -printLogStatisticNumber($unrecogCount, LOG_INFO, "%d files not recognized.\n") ; -if ($optVerify) -{ - for (my $i=0; $i < @verifyFailedCountMsgs; $i++) - { - printLogStatisticNumber($verifyFailedCount[$i], LOG_INFO, "Verify statistics:$verifyFailedCountMsgs[$i]=%d.\n") ; - } -} -elsif (!$optOem) -{ - printLogStatisticNumber($noDescrcount, LOG_INFO, "%d files has no Description.\n") ; - printLogStatisticNumber($NokiaCopyrCount, LOG_INFO, "%d files has Nokia copyright.\n") ; - printLogStatisticNumber($ExternalToNokiaCopyrCount, LOG_INFO, "%d files moved also to Nokia.\n") ; - printLogStatisticNumber($otherCopyrCount, LOG_INFO, "%d files has non-nokia copyright.\n") ; - printLogStatisticNumber($NoCopyrCount, LOG_INFO, "%d files has no copyright.\n") ; - printLogStatisticNumber($UnclearCopyrCount, LOG_INFO, "%d files has UNCLEAR copyright.\n") ; - printLogStatisticNumber($createCount, LOG_INFO, "%d new files.\n") ; - if ($optEpl) - { - printLogStatisticNumber($SflToEplChanges, LOG_INFO, "%d files changes from SFL to EPL license.\n") ; - } - else - { - printLogStatisticNumber($EplToSflChanges, LOG_INFO, "%d files changes from SFL to EPL license.\n") ; - } -} -else -{ - printLogStatisticNumber($SflToS60Changes, LOG_INFO, "%d files changes from SFL to S60 license.\n") ; - # printLog($EplToS60Changes, LOG_INFO, "%d files changes from EPL to S60 license.\n") ; - printLogStatisticNumber($LicenseChangeErrors, LOG_INFO, "%d errors upon license change.\n") ; -} - -printLog(LOG_INFO,"Time elapsed $elapsedTime.\n") ; - -if ($logFile) -{ - close LOG; -} -