# # Software Index, Copyright 2010, Software Index Project Team # Link: http://swi.sourceforge.net # # This file is part of Software Index Tool. # # Software Index is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3 of the License. # # Software Index 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with Software Index. If not, see . # use strict; use XML::Simple; use FileHandle; # # Export section # require Exporter; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $PREFERRED_PARSER); @ISA = qw(Exporter); @EXPORT = qw(swiLaunch); @EXPORT_OK = qw(); $VERSION = '1.0'; $PREFERRED_PARSER = undef; # # Subroutine for troubleshooting purposes # use Internal::Output; # # Include SWI libs # require SWI::Appraiser; require SWI::Converter; require SWI::Merger; require SWI::Processor; # # Global variables # my $config = undef; # # Enter point # sub swiLaunch { my $returnCode = 0; my $rootLocation = shift(); my $swiConfiguration = shift(); # $returnCode == 0 => no critical errors and warnings # $returnCode > 0 => no critical errors, there are warnings # $returnCode < 0 => there are critical errors if ( $returnCode >= 0 ) { if ( $swiConfiguration eq "" ) { STATUS("Configuration file should be specified!"); $returnCode = -1; } else { STATUS("Configuration file: $swiConfiguration."); } } if ( $returnCode >= 0 ) { if ( swiConfigurationValidate($swiConfiguration) != 0 ) { STATUS("Wrong configuration file!"); $returnCode = -2; } } if ( $returnCode >= 0 ) { # Generate report for every module separately for ( my $i = 0 ; $i <= $#{ $config->{"swi:modules"}->{"swi:module"} } ; $i++ ) { STATUS( "Processing module: '" . $config->{"swi:modules"}->{"swi:module"}[$i]->{"swi:name"} . "'." ); my $result = swiProcess( $config, $i, $rootLocation ); if ( $result < 0 ) { STATUS("The are problems to report the index for the module!"); $returnCode = -5; } elsif ( $result > 0 ) { STATUS("The are scan warnings and/or errors."); $returnCode += $result; } else { STATUS("The module has been processed succesfully."); } } } if ( $returnCode >= 0 ) { # Merge reports if ( swiMerge($config) ) { STATUS("The are problems to merge files to one report!"); $returnCode = -3; } else { STATUS("Merged report has been created."); } } if ( $returnCode >= 0 ) { # Add average/min/max/total values and generate final XML report if ( swiAppraise($config) ) { STATUS("The are problems to add average/min/max/total values!"); $returnCode = -4; } else { STATUS("Average/min/max/total values have been added."); } } if ( $returnCode >= 0 ) { # Convert results my $result = swiConvert($config); if ( $result < 0 ) { STATUS("The are problems to convert the report!"); $returnCode = -5; } elsif ( $result > 0 ) { STATUS( "Report has been converted. There are exceeded limitations."); $returnCode += $result; } else { STATUS("Report has been converted."); } } STATUS("Execution completed with exit code '$returnCode'."); return $returnCode; } sub swiConfigurationValidate { my $result = 0; $config = XMLin( shift(), ForceArray => [ "swi:module", "swi:rule", "swi:pattern" ] ); if ( !defined( $config->{'swi:info'} ) ) { STATUS("Wrong configuration: 'swi:info' section missed."); $result++; } else { if ( !defined( $config->{'swi:info'}->{'swi:version'} ) ) { STATUS( "Wrong configuration: 'swi:info/swi:version' section missed."); $result++; } elsif ( $config->{'swi:info'}->{'swi:version'} != 1 ) { STATUS( "Wrong configuration: Unsupported version of the configuration file. Check 'swi:info/swi:version' section." ); $result++; } if ( !defined( $config->{'swi:info'}->{'swi:project'} ) ) { STATUS( "Wrong configuration: 'swi:info/swi:project' section missed."); $result++; } else { if ( !defined( $config->{'swi:info'}->{'swi:project'}->{'swi:name'} ) ) { STATUS( "Wrong configuration: 'swi:info/swi:project/swi:name' section missed." ); $result++; } elsif ( $config->{'swi:info'}->{'swi:project'}->{'swi:name'} eq "" ) { STATUS( "Wrong configuration: 'swi:info/swi:project/swi:name' is empty." ); $result++; } } } if ( !defined( $config->{'swi:general'} ) || ref( $config->{'swi:general'} ) ne 'HASH' ) { $config->{'swi:general'} = {}; } if ( !defined( $config->{'swi:general'}->{'swi:debug'} ) || ref( $config->{'swi:general'}->{'swi:debug'} ) ne 'HASH' ) { $config->{'swi:general'}->{'swi:debug'} = {}; } if ( !defined( $config->{'swi:general'}->{'swi:debug'}->{'swi:enabled'} ) ) { $config->{'swi:general'}->{'swi:debug'}->{'swi:enabled'} = 'off'; } DEBUG_ENABLED( ( $config->{'swi:general'}->{'swi:debug'}->{'swi:enabled'} eq 'on' ) ? 1 : 0 ); if ( !defined( $config->{'swi:modules'} ) || ref( $config->{'swi:modules'} ) ne 'HASH' ) { STATUS("Wrong configuration: 'swi:modules' section missed."); $result++; } else { if ( !defined( $config->{'swi:modules'}->{'swi:module'} ) || ref( $config->{'swi:modules'}->{'swi:module'} ) ne 'ARRAY' ) { STATUS( "Wrong configuration: 'swi:modules/swi:module' section missed." ); $result++; } else { my $moduleId = 0; foreach my $module ( @{ $config->{'swi:modules'}->{'swi:module'} } ) { if ( !defined( $module->{'swi:name'} ) ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:name' section missed." ); $result++; } if ( !defined( $module->{'swi:location'} ) ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:location' section missed." ); $result++; } if ( !defined( $module->{'swi:files'} ) || ref( $module->{'swi:files'} ) ne 'HASH' ) { $module->{'swi:files'} = {}; } if ( !defined( $module->{'swi:files'}->{'swi:include'} ) ) { $module->{'swi:files'}->{'swi:include'} = '.*'; } if ( !defined( $module->{'swi:files'}->{'swi:exclude'} ) ) { $module->{'swi:files'}->{'swi:exclude'} = ''; } if ( !defined( $module->{'swi:preprocessor'} ) || ref( $module->{'swi:preprocessor'} ) ne 'HASH' ) { $module->{'swi:preprocessor'} = {}; } if ( !defined( $module->{'swi:preprocessor'}->{'swi:rule'} ) ) { $module->{'swi:preprocessor'}->{'swi:rule'} = []; } my $ruleId = 0; foreach my $rule ( @{ $module->{'swi:preprocessor'}->{'swi:rule'} } ) { if ( !defined( $rule->{'swi:filepattern'} ) || $rule->{'swi:filepattern'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:preprocessor/swi:rule[$ruleId]/swi:filepattern' section missed." ); $result++; } if ( !defined( $rule->{'swi:searchpattern'} ) || $rule->{'swi:searchpattern'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:preprocessor/swi:rule[$ruleId]/swi:searchpattern' section missed." ); $result++; } if ( !defined( $rule->{'swi:replacepattern'} ) || $rule->{'swi:replacepattern'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:preprocessor/swi:rule[$ruleId]/swi:replacepattern' section missed." ); $result++; } $ruleId++; } if ( !defined( $module->{'swi:scanner'} ) || ref( $module->{'swi:scanner'} ) ne 'HASH' ) { $module->{'swi:scanner'} = {}; } if ( !defined( $module->{'swi:scanner'}->{'swi:rule'} ) ) { $module->{'swi:scanner'}->{'swi:rule'} = []; } $ruleId = 0; foreach my $rule ( @{ $module->{'swi:scanner'}->{'swi:rule'} } ) { if ( !defined( $rule->{'swi:filepattern'} ) || $rule->{'swi:filepattern'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:scanner/swi:rule[$ruleId]/swi:filepattern' section missed." ); $result++; } if ( !defined( $rule->{'swi:searchpattern'} ) || $rule->{'swi:searchpattern'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:scanner/swi:rule[$ruleId]/swi:searchpattern' section missed." ); $result++; } if ( !defined( $rule->{'swi:messagepattern'} ) || $rule->{'swi:messagepattern'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:scanner/swi:rule[$ruleId]/swi:messagepattern' section missed." ); $result++; } if ( !defined( $rule->{'swi:codecontent'} ) || $rule->{'swi:codecontent'} eq "" ) { $rule->{'swi:codecontent'} = 'purified'; } $ruleId++; } if ( !defined( $module->{'swi:scanner'}->{'swi:suppress'} ) ) { $module->{'swi:scanner'}->{'swi:suppress'} = {}; } if ( !defined( $module->{'swi:scanner'}->{'swi:suppress'} ->{'swi:pattern'} ) ) { $module->{'swi:scanner'}->{'swi:suppress'} ->{'swi:pattern'} = []; } my $patternId = 0; foreach my $pattern ( @{ $module->{'swi:scanner'}->{'swi:suppress'} ->{'swi:pattern'} } ) { if ( ref($pattern) ne 'HASH' ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:scanner/swi:suppress/swi:pattern[$patternId]' section is incorrect." ); $result++; } else { if ( !defined( $pattern->{'swi:message'} ) || $pattern->{'swi:message'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:scanner/swi:suppress/swi:pattern[$patternId]/swi:message' field is empty." ); $result++; } if ( !defined( $pattern->{'content'} ) || $pattern->{'content'} eq "" ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:scanner/swi:suppress/swi:pattern[$patternId]' object pattern is empty." ); $result++; } } $patternId++; } if ( !defined( $module->{'swi:indexer:common'} ) || ref( $module->{'swi:indexer:common'} ) ne 'HASH' ) { $module->{'swi:indexer:common'} = {}; } if ( !defined( $module->{'swi:indexer:dup'} ) || ref( $module->{'swi:indexer:dup'} ) ne 'HASH' ) { $module->{'swi:indexer:dup'} = {}; } if ( !defined( $module->{'swi:indexer:dup'}->{'swi:codecontent'} ) ) { $module->{'swi:indexer:dup'}->{'swi:codecontent'} = 'purified'; } if ( !defined( $module->{'swi:indexer:dup'}->{'swi:enabled'} ) ) { $module->{'swi:indexer:dup'}->{'swi:enabled'} = 'on'; } if ( !defined( $module->{'swi:indexer:dup'}->{'swi:minlength'} ) ) { $module->{'swi:indexer:dup'}->{'swi:minlength'} = 100; } if ( $module->{'swi:indexer:dup'}->{'swi:minlength'} <= 0 ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:indexer:dup/swi:minlength' can not be less than or equal to zero." ); $result++; } if ( !defined( $module->{'swi:indexer:dup'}->{'swi:proximity'} ) ) { $module->{'swi:indexer:dup'}->{'swi:proximity'} = 100; } if ( $module->{'swi:indexer:dup'}->{'swi:proximity'} <= 0 || $module->{'swi:indexer:dup'}->{'swi:proximity'} > 100 ) { STATUS( "Wrong configuration: 'swi:modules/swi:module[$moduleId]/swi:indexer:dup/swi:proximity' should be in the range from 1 till 100." ); $result++; } if ( !defined( $module->{'swi:indexer:dup'}->{'swi:globalcode'} ) ) { $module->{'swi:indexer:dup'}->{'swi:globalcode'} = 'off'; } if ( !defined( $module->{'swi:indexer:gcov'} ) || ref( $module->{'swi:indexer:gcov'} ) ne 'HASH' ) { $module->{'swi:indexer:gcov'} = {}; } if ( !defined( $module->{'swi:indexer:gcov'}->{'swi:enabled'} ) ) { $module->{'swi:indexer:gcov'}->{'swi:enabled'} = 'off'; } if ( !defined( $module->{'swi:indexer:gcov'}->{'swi:filepattern'} ) ) { $module->{'swi:indexer:gcov'}->{'swi:filepattern'} = '.*'; } if ( !defined( $module->{'swi:indexer:gcov'}->{'swi:sourcefile'} ) ) { $module->{'swi:indexer:gcov'}->{'swi:sourcefile'} = '(.*)[.][cChH][pP]?[pP]?'; } if ( !defined( $module->{'swi:indexer:gcov'}->{'swi:gcdafile'} ) ) { $module->{'swi:indexer:gcov'}->{'swi:gcdafile'} = '${1}.gcda'; } $moduleId++; } } } if ( !defined( $config->{'swi:report'} ) || ref( $config->{'swi:report'} ) ne 'HASH' ) { STATUS("Wrong configuration: 'swi:report' section missed."); $result++; } else { if ( !defined( $config->{'swi:report'}->{'swi:destination'} ) ) { STATUS( "Wrong configuration: 'swi:report/swi:destination' section missed." ); $result++; } if ( !defined( $config->{'swi:report'}->{'swi:xml'} ) ) { STATUS("Wrong configuration: 'swi:report/swi:xml' section missed."); $result++; } else { if ( !defined( $config->{'swi:report'}->{'swi:xml'}->{'swi:name'} ) ) { STATUS( "Wrong configuration: 'swi:report/swi:xml/swi:name' section is empty." ); $result++; } } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ) ) { STATUS( "Wrong configuration: 'swi:report/swi:notifications' section missed." ); $result++; } else { if ( !defined( $config->{'swi:report'}->{'swi:notifications'}->{'swi:name'} ) ) { STATUS( "Wrong configuration: 'swi:report/swi:notifications/swi:name' section is empty." ); $result++; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'} ) || ref( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'} ) ne 'HASH' ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:error'} = {}; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'}->{'swi:added'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:error'} ->{'swi:added'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'}->{'swi:removed'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:error'} ->{'swi:removed'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'}->{'swi:modified'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:error'} ->{'swi:modified'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'}->{'swi:cloned'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:error'} ->{'swi:cloned'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:error'}->{'swi:unmodified'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:error'} ->{'swi:unmodified'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:print'} ) || ref( $config->{'swi:report'}->{'swi:notifications'} ->{'swi:print'} ) ne 'HASH' ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} = {}; } swiUtilConfigFill_PrintSection($config, 'swi:added'); swiUtilConfigFill_PrintSection($config, 'swi:removed'); swiUtilConfigFill_PrintSection($config, 'swi:modified'); swiUtilConfigFill_PrintSection($config, 'swi:cloned'); swiUtilConfigFill_PrintSection($config, 'swi:unmodified'); } } # swi:limits section is verified in runtime # no precheck currently DEBUG( "Configuration structure is: " . Dumper($config) ); return $result; } sub swiUtilConfigFill_PrintSection { my $config = shift(); my $modType = shift(); if ( !defined( $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType} ) || ref( $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType} ) ne 'HASH' ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType} = {}; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:failures'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:failures'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:modifications'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:modifications'} = 'on'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:duplications'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:duplications'} = 'off'; } if ( !defined( $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:scanmessages'} ) ) { $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'} ->{$modType}->{'swi:scanmessages'} = 'on'; } } return 1;