Browse Source

-- Date: 2010/02/14
Reference: noref
Issue type: feature
Severity: Major
Module(s): Appraiser
Description: Relative limits are possible with zero numbers
Infinity/-Infinity statistics supported

-- Date: 2010/02/14
Reference: noref
Issue type: bug
Severity: Major
Module(s): Coverage indexer
Description: Empty gcov data (no calls, no branches) is processed correctly now

-- Date: 2010/02/14
Reference: noref
Issue type: bug
Severity: Minor
Module(s): Converter
Description: Duplication messages are deactivated by default
However, they are always printed if there corresponding failures

-- Date: 2010/02/14
Reference: noref
Issue type: bug
Severity: Minor
Module(s): Scanner
Description: Line offset bug fixed

avkonst 15 years ago
parent
commit
3686184b35
7 changed files with 349 additions and 199 deletions
  1. 31 0
      changelog.txt
  2. 166 125
      lib/SWI/Appraiser.pm
  3. 33 22
      lib/SWI/Converter.pm
  4. 1 1
      lib/SWI/Launcher.pm
  5. 56 26
      lib/SWI/Processor.pm
  6. 57 20
      swi_config_sample.xml
  7. 5 5
      test/swi_config_ddd.xml

+ 31 - 0
changelog.txt

@@ -20,7 +20,37 @@
 ____________________________________________
 
 
+-- 2010/02/XX: VERSION 0.9.1 released
+
+       -- Date:         2010/02/14
+          Reference:    noref
+          Issue type:   feature
+          Severity:     Major
+          Module(s):    Appraiser
+          Description:  Relative limits are possible with zero numbers
+                        Infinity/-Infinity statistics supported
+
+       -- Date:         2010/02/14
+          Reference:    noref
+          Issue type:   bug
+          Severity:     Major
+          Module(s):    Coverage indexer
+          Description:  Empty gcov data (no calls, no branches) is processed correctly now
+
+       -- Date:         2010/02/14
+          Reference:    noref
+          Issue type:   bug
+          Severity:     Minor
+          Module(s):    Converter
+          Description:  Duplication messages are deactivated by default
+                        However, they are always printed if there corresponding failures
+
+       -- Date:         2010/02/14
+          Reference:    noref
+          Issue type:   bug
+          Severity:     Minor
+          Module(s):    Scanner
+          Description:  Line offset bug fixed
 
        -- Date:         2010/02/12
           Reference:    noref

+ 166 - 125
lib/SWI/Appraiser.pm

@@ -113,7 +113,8 @@ sub swiAppraise
                           $subStat->{$keySubStat}->{'swi:exact'};
                         $fileStat->{$keyStat}->{$keySubStat}->{"swi:average"} =
                           $fileStat->{$keyStat}->{$keySubStat}->{"swi:total"} /
-                          $fileStat->{"swi:count"}->{"swi:functions"}->{'swi:exact'};
+                          $fileStat->{"swi:count"}->{"swi:functions"}
+                          ->{'swi:exact'};
 
                         # add total per module
                         $moduleStat->{$keyStat}->{$keySubStat}->{"swi:total"} +=
@@ -122,7 +123,8 @@ sub swiAppraise
                           ->{"swi:average"} =
                           $moduleStat->{$keyStat}->{$keySubStat}
                           ->{"swi:total"} /
-                          $moduleStat->{"swi:count"}->{"swi:functions"}->{'swi:exact'};
+                          $moduleStat->{"swi:count"}->{"swi:functions"}
+                          ->{'swi:exact'};
 
                         # add total per project
                         $projectStat->{$keyStat}->{$keySubStat}
@@ -132,7 +134,8 @@ sub swiAppraise
                           ->{"swi:average"} =
                           $projectStat->{$keyStat}->{$keySubStat}
                           ->{"swi:total"} /
-                          $projectStat->{"swi:count"}->{"swi:functions"}->{'swi:exact'};
+                          $projectStat->{"swi:count"}->{"swi:functions"}
+                          ->{'swi:exact'};
 
                         # add minimum per file
                         if (
@@ -433,7 +436,7 @@ sub swiAppraise
                                     =~ m/$objPattern/ )
                                 {
                                     $refData->{'swi:scan:suppress'} = 'on';
-                                    $pattern->{'swi:used'} = 1;
+                                    $pattern->{'swi:used'}          = 1;
                                     last;
                                 }
                             }
@@ -696,7 +699,7 @@ sub swiAppraise
     }
     print $fh "  </swi:statistic>\n";
     print $fh "</swi:report>\n";
-    
+
     swiCheckUselessPatterns($config);
 
     return 0;
@@ -719,142 +722,177 @@ sub swiStatisticLevelGet
         defined( $config->{"swi:limits"}->{$keyStat}->{$keySubStat}->{$type} ) )
     {
         my $limit = $config->{"swi:limits"}->{$keyStat}->{$keySubStat}->{$type};
-        my $factor = 1;
 
-        if ( defined( $limit->{"swi:relation"} ) )
+        my $objectPattern = $limit->{"swi:objectpattern"};
+        if ( defined($objectPattern) && $objName !~ m/$objectPattern/ )
         {
-            my @relation = undef;
-            @relation = split( /\//, $limit->{"swi:relation"} );
-
-            $factor =
-              $objStat->{ $relation[0] }->{ $relation[1] }->{ $relation[2] };
-
-            if ( !defined($factor) || $factor == 0 )
-            {
-                STATUS(
-"Wrong configuration for the limit '$keyStat/$keySubStat/$type'. Relation "
-                      . $limit->{"swi:relation"}
-                      . " is not found or points to zero value for object '$objName'"
-                );
-                $factor = 1;
-            }
+            $returnResult[2] = '[limit not applied]';
         }
-
-        $statValue = $objStat->{$keyStat}->{$keySubStat}->{$type} / $factor;
-        $statValue = sprintf( "%.2f", $statValue );
-
-        if (   $limit->{"swi:warning"} > $limit->{"swi:notice"}
-            && $limit->{"swi:notice"} > $limit->{"swi:info"} )
+        else
         {
-            if ( $statValue > $limit->{"swi:warning"} )
+            if ( defined( $limit->{"swi:relation"} ) )
             {
-                $returnResult[0] = "warning";
-                $returnResult[2] = "["
-                  . $statValue
-                  . " greater than "
-                  . $limit->{"swi:warning"} . "]";
-            }
-            elsif ( $statValue > $limit->{"swi:notice"} )
-            {
-                $returnResult[0] = "notice";
-                $returnResult[2] = "["
-                  . $statValue
-                  . " greater than "
-                  . $limit->{"swi:notice"} . "]";
-            }
-            elsif ( $statValue > $limit->{"swi:info"} )
-            {
-                $returnResult[0] = "info";
-                $returnResult[2] = "["
-                  . $statValue
-                  . " greater than "
-                  . $limit->{"swi:info"} . "]";
+                my @relation = undef;
+                @relation = split( /\//, $limit->{"swi:relation"} );
+
+                my $factor =
+                  $objStat->{ $relation[0] }->{ $relation[1] }
+                  ->{ $relation[2] };
+
+                if ( !defined($factor) || $factor == 0 )
+                {
+                    STATUS(
+"Wrong configuration for the limit '$keyStat/$keySubStat/$type'. Relation "
+                          . $limit->{"swi:relation"}
+                          . " is not found for the object '$objName'"
+                    );
+                    $factor = 0;
+                }
+                if ($factor == 0)
+                {
+                    # Devide zero by zero, equals to 1
+                    if ($objStat->{$keyStat}->{$keySubStat}->{$type} == 0)
+                    {
+                        $statValue = "1.00";
+                    }
+                    # Devide negative number by zero, equals to -infinity
+                    elsif ($objStat->{$keyStat}->{$keySubStat}->{$type} < 0)
+                    {
+                        $statValue = "-Infinity";        
+                    }
+                    # Devide positive number by zero, equals to infinity
+                    else
+                    {
+                        $statValue = "Infinity";
+                    }
+                }
+                else
+                {
+                    $statValue = $objStat->{$keyStat}->{$keySubStat}->{$type} / $factor;
+                    $statValue = sprintf( "%.2f", $statValue );
+                }
             }
             else
             {
-                $returnResult[0] = "regular";
+                $statValue = sprintf( "%.2f", $objStat->{$keyStat}->{$keySubStat}->{$type} );
             }
-        }
-        elsif ($limit->{"swi:warning"} < $limit->{"swi:notice"}
-            && $limit->{"swi:notice"} < $limit->{"swi:info"} )
-        {
-            if ( $statValue < $limit->{"swi:warning"} )
-            {
-                $returnResult[0] = "warning";
-                $returnResult[2] = "["
-                  . $statValue
-                  . " less than "
-                  . $limit->{"swi:warning"} . "]";
-            }
-            elsif ( $statValue < $limit->{"swi:notice"} )
+
+            if (   $limit->{"swi:warning"} > $limit->{"swi:notice"}
+                && $limit->{"swi:notice"} > $limit->{"swi:info"} )
             {
-                $returnResult[0] = "notice";
-                $returnResult[2] = "["
-                  . $statValue
-                  . " less than "
-                  . $limit->{"swi:notice"} . "]";
+                if ( $statValue eq "Infinity" || $statValue > $limit->{"swi:warning"} )
+                {
+                    $returnResult[0] = "warning";
+                    $returnResult[2] = "["
+                      . $statValue
+                      . " greater than "
+                      . $limit->{"swi:warning"} . "]";
+                }
+                elsif ( $statValue > $limit->{"swi:notice"} )
+                {
+                    $returnResult[0] = "notice";
+                    $returnResult[2] = "["
+                      . $statValue
+                      . " greater than "
+                      . $limit->{"swi:notice"} . "]";
+                }
+                elsif ( $statValue > $limit->{"swi:info"} )
+                {
+                    $returnResult[0] = "info";
+                    $returnResult[2] = "["
+                      . $statValue
+                      . " greater than "
+                      . $limit->{"swi:info"} . "]";
+                }
+                else
+                {
+                    $returnResult[0] = "regular";
+                }
             }
-            elsif ( $statValue < $limit->{"swi:info"} )
+            elsif ($limit->{"swi:warning"} < $limit->{"swi:notice"}
+                && $limit->{"swi:notice"} < $limit->{"swi:info"} )
             {
-                $returnResult[0] = "info";
-                $returnResult[2] =
-                  "[" . $statValue . " less than " . $limit->{"swi:info"} . "]";
+                if ( $statValue eq "-Infinity" || $statValue < $limit->{"swi:warning"} )
+                {
+                    $returnResult[0] = "warning";
+                    $returnResult[2] = "["
+                      . $statValue
+                      . " less than "
+                      . $limit->{"swi:warning"} . "]";
+                }
+                elsif ( $statValue < $limit->{"swi:notice"} )
+                {
+                    $returnResult[0] = "notice";
+                    $returnResult[2] = "["
+                      . $statValue
+                      . " less than "
+                      . $limit->{"swi:notice"} . "]";
+                }
+                elsif ( $statValue < $limit->{"swi:info"} )
+                {
+                    $returnResult[0] = "info";
+                    $returnResult[2] = "["
+                      . $statValue
+                      . " less than "
+                      . $limit->{"swi:info"} . "]";
+                }
+                else
+                {
+                    $returnResult[0] = "regular";
+                }
             }
             else
             {
-                $returnResult[0] = "regular";
-            }
-        }
-        else
-        {
-            STATUS(
+                STATUS(
 "Wrong settings in configuration file (swi:limits section): swi:limit/$keyStat/$keySubStat/$type"
-            );
-            $returnResult[0] = "unresolved";
-        }
+                );
+                $returnResult[0] = "unresolved";
+            }
 
-        # check if suppressed
-        my $isFound = 0;
+            # check if suppressed
+            my $isFound = 0;
 
-      LOOPPATTERNS:
-        foreach ( @{ $limit->{"swi:suppress"}->{"swi:pattern"} } )
-        {
-            my $pattern = $_;
-            if ( ref($pattern) eq "HASH" && defined( $pattern->{"swi:level"} ) )
+          LOOPPATTERNS:
+            foreach ( @{ $limit->{"swi:suppress"}->{"swi:pattern"} } )
             {
-                my $content = $pattern->{"content"};
-                if ( $objName =~ m/$content/ )
+                my $pattern = $_;
+                if ( ref($pattern) eq "HASH"
+                    && defined( $pattern->{"swi:level"} ) )
                 {
-                    if ( $isFound == 0 )
+                    my $content = $pattern->{"content"};
+                    if ( $objName =~ m/$content/ )
                     {
-                        $returnResult[1] = $pattern->{"swi:level"};
-                        $pattern->{'swi:used'} = 1;
-                        $isFound = 1;
-                    }
-                    else
-                    {
-
-                        # This object is matched by several patterns
-                        if ( $returnResult[1] ne $pattern->{"swi:level"} )
+                        if ( $isFound == 0 )
+                        {
+                            $returnResult[1]       = $pattern->{"swi:level"};
+                            $pattern->{'swi:used'} = 1;
+                            $isFound               = 1;
+                        }
+                        else
                         {
 
-                            # and levels are not equal in different patterns
-                            STATUS(
+                            # This object is matched by several patterns
+                            if ( $returnResult[1] ne $pattern->{"swi:level"} )
+                            {
+
+                                # and levels are not equal in different patterns
+                                STATUS(
 "Configuration is wrong: $objName is matched by several patterns"
-                            );
-                            $returnResult[1] = "unresolved";
+                                );
+                                $returnResult[1] = "unresolved";
+                            }
                         }
                     }
                 }
-            }
-            else
-            {
-                STATUS(
+                else
+                {
+                    STATUS(
 "Wrong settings in configuration file (swi:limits section): swi:limits/$keyStat/$keySubStat/$type: "
-                      . "Level is missed in pattern for the object '$objType'"
-                );
-                $returnResult[1] = "unresolved";
-                $returnResult[2] = "[]";
+                          . "Level is missed in pattern for the object '$objType'"
+                    );
+                    $returnResult[1] = "unresolved";
+                    $returnResult[2] = "[]";
+                }
             }
         }
     }
@@ -929,36 +967,39 @@ sub swiReportModificationGet
 sub swiCheckUselessPatterns
 {
     my $root = shift();
-    if (ref($root) eq "HASH")
+    if ( ref($root) eq "HASH" )
     {
-        foreach my $key (keys %{$root})
+        foreach my $key ( keys %{$root} )
         {
-            if ($key eq 'swi:pattern')
+            if ( $key eq 'swi:pattern' )
             {
-                foreach my $pattern (@{$root->{'swi:pattern'}})
+                foreach my $pattern ( @{ $root->{'swi:pattern'} } )
                 {
-                    if (!defined($pattern->{'swi:used'}) || $pattern->{'swi:used'} == 0)
+                    if ( !defined( $pattern->{'swi:used'} )
+                        || $pattern->{'swi:used'} == 0 )
                     {
                         my $data = Dumper($pattern);
                         $data =~ s/\n/ /g;
                         $data =~ s/\s+/ /g;
-                        STATUS("Useless suppress option detected with the following content: $data");
+                        STATUS(
+"Useless suppress option detected with the following content: $data"
+                        );
                     }
                 }
-                
+
                 return;
             }
-            swiCheckUselessPatterns($root->{$key});         
+            swiCheckUselessPatterns( $root->{$key} );
         }
     }
-    elsif (ref($root) eq "ARRAY")
+    elsif ( ref($root) eq "ARRAY" )
     {
-        foreach (@{$root})
+        foreach ( @{$root} )
         {
-            return swiCheckUselessPatterns($_);         
+            return swiCheckUselessPatterns($_);
         }
     }
-    
+
     return;
 }
 

+ 33 - 22
lib/SWI/Converter.pm

@@ -199,6 +199,7 @@ sub swiNotificationPrint
     }
 
     # Print 'swi:failures'
+    my $areThereDupViolations = 0;
     foreach my $keyStat ( keys %$objStat )
     {
         my $subStat = $objStat->{$keyStat};
@@ -241,33 +242,14 @@ sub swiNotificationPrint
                         eq "on" )
                     {
                         print $file $notification;
+                        print $file "\n";
 
-                        # Print 'swi:duplications'
                         if (   $keyStat eq "swi:duplication"
                             && $keySubStat eq "swi:symbols"
-                            && $config->{"swi:report"}->{"swi:notifications"}
-                            ->{"swi:print"}->{ "swi:" . $objDiff }
-                            ->{"swi:duplications"} eq "on" )
+                            && $type       eq 'swi:exact' )
                         {
-                            die('Internal Error occured!')
-                              if not defined($objRefs);
-                            print $file "\n";
-                            foreach my $dupData ( @{$objRefs} )
-                            {
-                                if ( $dupData->{'swi:ref:type'} eq 'dup' )
-                                {
-                                    print $file $modLocation . "/"
-                                      . $dupData->{'swi:dup:file'} . ":"
-                                      . $dupData->{'swi:dup:line'}
-                                      . ": warning: '"
-                                      . $dupData->{'swi:dup:size'}
-                                      . "' executable symbols are duplicated in '"
-                                      . $dupData->{'swi:dup:function'}
-                                      . "' function\n";
-                                }
-                            }
+                            $areThereDupViolations = 1;
                         }
-                        print $file "\n";
                     }
 
                     if ( $config->{"swi:report"}->{"swi:notifications"}
@@ -306,6 +288,35 @@ sub swiNotificationPrint
         }
     }
 
+    # Print 'swi:duplications'
+    if (
+        $areThereDupViolations == 1
+        || $config->{"swi:report"}->{"swi:notifications"}->{"swi:print"}
+        ->{ "swi:" . $objDiff }->{"swi:duplications"} eq "on"
+      )
+    {
+        my $isPrinted = 0;
+        foreach my $dupData ( @{$objRefs} )
+        {
+            if ( $dupData->{'swi:ref:type'} eq 'dup' )
+            {
+                print $file $modLocation . "/"
+                  . $dupData->{'swi:dup:file'} . ":"
+                  . $dupData->{'swi:dup:line'}
+                  . ": warning: '"
+                  . $dupData->{'swi:dup:size'}
+                  . "' executable symbols are duplicated in '"
+                  . $dupData->{'swi:dup:function'}
+                  . "' function\n";
+                $isPrinted = 1;
+            }
+        }
+        if ($isPrinted == 1)
+        {
+            print $file "\n";
+        }
+    }
+
     # Print 'swi:scanmessages'
     if ( $config->{"swi:report"}->{"swi:notifications"}->{"swi:print"}
         ->{ "swi:" . $objDiff }->{"swi:scanmessages"} eq "on" )

+ 1 - 1
lib/SWI/Launcher.pm

@@ -722,7 +722,7 @@ sub swiUtilConfigFill_PrintSection
       )
     {
         $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'}
-          ->{$modType}->{'swi:duplications'} = 'on';
+          ->{$modType}->{'swi:duplications'} = 'off';
     }
     if (
         !defined(

+ 56 - 26
lib/SWI/Processor.pm

@@ -204,9 +204,13 @@ sub swiProcess
         $dupindexHandler =
           open3( $dupindexIn, $dupindexOut, $dupindexErr,
             "$rootLocation/dupindex/bin/dupindex.exe" );
-        if (!defined($dupindexHandler) || !defined($dupindexIn) || !defined($dupindexOut) )
+        if (   !defined($dupindexHandler)
+            || !defined($dupindexIn)
+            || !defined($dupindexOut) )
         {
-             die("Can not start the internal platform native tool '$rootLocation/dupindex/bin/dupindex.exe'");
+            die(
+"Can not start the internal platform native tool '$rootLocation/dupindex/bin/dupindex.exe'"
+            );
         }
 
         my $dupfinderSettings =
@@ -655,16 +659,21 @@ sub swiSourceIndexAdd
     {
         my $function = $functionsData->{$functionName};
 
-        my $block = {};
+        my $block       = {};
+        my $blockOffset = {};
+
+        # Initialize function name
         $block->{'functionname'} = $functionName;
         $block->{'functionname'} =~
 s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeContainerDelimeter)*($regexpCodeFunctionIdentifier)/$3/;
+        $blockOffset->{'functionname'} = $function->{'swi:line:headerstart'};
 
         if ( $functionName ne $regexpCodeGlobalFunctionName )
         {
 
             # Get content
-            $block->{'initial'} = "";
+            $block->{'initial'}       = "";
+            $blockOffset->{'initial'} = $function->{'swi:line:commentstart'};
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -673,7 +682,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
                 $block->{'initial'} .= $block_Initial[$i] . "\n";
             }
-            $block->{'code'} = "";
+            $block->{'code'}       = "";
+            $blockOffset->{'code'} = $function->{'swi:line:commentstart'};
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -682,7 +692,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
                 $block->{'code'} .= $block_Code[$i] . "\n";
             }
-            $block->{'comments'} = "";
+            $block->{'comments'}       = "";
+            $blockOffset->{'comments'} = $function->{'swi:line:commentstart'};
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -691,7 +702,9 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
                 $block->{'comments'} .= $block_Comment[$i] . "\n";
             }
-            $block->{'nopreprocessor'} = "";
+            $block->{'nopreprocessor'}       = "";
+            $blockOffset->{'nopreprocessor'} =
+              $function->{'swi:line:commentstart'};
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -700,7 +713,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
                 $block->{'nopreprocessor'} .= $block_NoPrep[$i] . "\n";
             }
-            $block->{'nostrings'} = "";
+            $block->{'nostrings'}       = "";
+            $blockOffset->{'nostrings'} = $function->{'swi:line:commentstart'};
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -716,7 +730,10 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                   $function->{'swi:pos:headerstart'}
               )
               . "\n";
-            $block->{'commentshead'} = "";
+            $blockOffset->{'purified'} = $function->{'swi:line:headerstart'};
+            $block->{'commentshead'}   = "";
+            $blockOffset->{'commentshead'} =
+              $function->{'swi:line:commentstart'};
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i < $function->{'swi:line:headerstart'} ;
@@ -726,7 +743,6 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                 $block->{'commentshead'} .= $block_Comment[$i] . "\n";
             }
 
-            # functionname created above
             $block->{'functionhead'} = substr(
                 $block_Purified,
                 $function->{'swi:pos:headerstart'},
@@ -734,6 +750,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                   $function->{'swi:pos:headerstart'}
               )
               . "\n";
+            $blockOffset->{'functionhead'} =
+              $function->{'swi:line:headerstart'};
             $block->{'functionbody'} = substr(
                 $block_Purified,
                 $function->{'swi:pos:blockstart'},
@@ -741,25 +759,37 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                   $function->{'swi:pos:blockstart'}
               )
               . "\n";
+            $blockOffset->{'functionbody'} = $function->{'swi:line:blockstart'};
         }
         else
         {
             $block->{'initial'} =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Initial );
-            $block->{'code'} =
+            $blockOffset->{'initial'} = 0;
+            $block->{'code'}          =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Code );
-            $block->{'comments'} =
+            $blockOffset->{'code'} = 0;
+            $block->{'comments'}   =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Comment );
+            $blockOffset->{'comments'} = 0;
             $block->{'nopreprocessor'} =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_NoPrep );
-            $block->{'nostrings'} =
+            $blockOffset->{'nopreprocessor'} = 0;
+            $block->{'nostrings'}            =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_NoStr );
-            $block->{'purified'} =
+            $blockOffset->{'nostrings'} = 0;
+            $block->{'purified'}        =
               swiSourceCodeGlobalGet( $functionsData, undef, $block_Purified );
-            $block->{'commentshead'} =
+            $blockOffset->{'purified'} = 0;
+            $block->{'commentshead'}   =
               swiSourceCodeGlobalGet( $functionsData,
                 $function->{'swi:line:headerstart'},
                 @block_Comment );
+            $blockOffset->{'commentshead'} = 0;
+            $block->{'functionhead'}       = "";    # N/A
+            $blockOffset->{'functionhead'} = 0;
+            $block->{'functionbody'}       = "";    # N/A
+            $blockOffset->{'functionbody'} = 0;
         }
 
         # Initialize container
@@ -793,12 +823,12 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
         # Note: this statistic is used to detect differences
         # Global code is compared without new lines
         my $initialContent = $block->{'initial'};
-        if ($functionName eq $regexpCodeGlobalFunctionName)
+        if ( $functionName eq $regexpCodeGlobalFunctionName )
         {
             $initialContent =~ s/\n+//g;
         }
         $function->{'swi:statistic'}->{'swi:length'}->{'swi:source'}
-          ->{'swi:exact'} = length( $initialContent );
+          ->{'swi:exact'} = length($initialContent);
 
         # Calculate swi:length->swi:executable
         $function->{'swi:statistic'}->{'swi:length'}->{'swi:executable'}
@@ -882,7 +912,7 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                     @{ $function->{'swi:reference'} },
                     swiSourceCodeScan(
                         $file,
-                        $function->{'swi:line:headerstart'},
+                        $blockOffset->{ $rule->{'swi:codecontent'} },
                         $block->{ $rule->{'swi:codecontent'} },
                         $rule->{'swi:searchpattern'},
                         $rule->{'swi:messagepattern'}
@@ -1014,14 +1044,16 @@ sub swiSourceIndexGcovAdd
     my $fh = new FileHandle( $location . "/" . $gcdaFile, "r" );
     if ( !defined($fh) )
     {
-        STATUS("gcda file is not found '$location/$gcdaFile'.");
+        STATUS("gcda file '$location/$gcdaFile' is not found  for the '$file' source.");
     }
     else
     {
         my $gcovCommand = 'gcov -f -b $location/$gcdaFile';
-        STATUS("Calling command '$gcovCommand'...");
-
+        
         my $gcovData = `$gcovCommand`;
+        $gcovData =~ s/No executable lines/Lines executed:100.OO% of O/g; 
+        $gcovData =~ s/No calls/Calls executed:100.00% of O/g; 
+        $gcovData =~ s/No branches/Branches executed:100.O0% of O\nTaken at least once:100.O0% of O/g; 
         my @covData  = split( "\n\n", $gcovData );
 
         foreach (@covData)
@@ -1063,9 +1095,6 @@ m/^Function\s+\'(.*)\'\s+Lines\s+executed:(.*)%\s+of\s+(.*)\s+Branches\s+execute
             else
             {
                 STATUS(
-"Parsing of source file is incorrect or gcda file is corrupted."
-                );
-                STATUS(
 "gcov reports the data for '$functionName' function but SWI parser did not detect it"
                 );
                 $exitCode++;
@@ -1156,8 +1185,9 @@ m/^($regexpCodeFunctionModifier)*($regexpCodeFunctionIdentifier)($regexpCodeFunc
                     # Remove empty symbols in identifier
                     $word =~ s/\s+$//;
                     $word =~ s/[\n\t ]+/ /g;
-                    $word =~ s/\s*$regexpCodeContainerDelimeter\s*/$regexpCodeContainerDelimeter/;
-                    
+                    $word =~
+s/\s*$regexpCodeContainerDelimeter\s*/$regexpCodeContainerDelimeter/;
+
                     # Remove empty symbols in modifier
                     $mod =~ s/^\s*//;
                     $mod =~ s/\s*$//;

+ 57 - 20
swi_config_sample.xml

@@ -271,7 +271,7 @@
               which is interpolated before: variables ${1}, ${2}, ... are replaced by actual strings
               from 'swi:searchpattern' regexp hooks.
           -->
-          <swi:searchpattern>([^_a-zA-Z0-9])DECLARE_HANDLER\(([^_a-zA-Z0-9])\)</swi:searchpattern>
+          <swi:searchpattern>([^_a-zA-Z0-9])DECLARE_HANDLER\(([_a-zA-Z0-9]+)\)</swi:searchpattern>
           <swi:replacepattern>${1}int ${2}(unsigned int stateId, unsigned int eventId, struct EVENT_DATA_TYPE eventData)</swi:replacepattern>
         </swi:rule>
         <!--
@@ -640,7 +640,7 @@
             
             By default, all files are affected.
         -->
-        <swi:filepattern>.*</swi:filepattern>
+        <swi:filepattern>^.*[.][cC][pP]?[pP]?$</swi:filepattern>
         <!--
             The coverage statistic is avaialble in 'gcda' files.
             gcov tool reads these files and reports the information.
@@ -662,14 +662,14 @@
             
             The example below demostrates the case of mapping:
                  from 'file.c' to 'file.gcda'
-                 from 'otehrfile.h' to 'otherfile.gcda'
+                 from 'otehrfile.c' to 'otherfile.gcda'
                  and so on...
             
             If the 'gcda' file is not found, coverage statistic is not collected and not reported.
             
-            The example below demonstrates the default mapping scheme options are missed.
+            The example below demonstrates the default mapping scheme if options are missed.
         -->
-        <swi:sourcefile>(.*)[.][cChH][pP]?[pP]?</swi:sourcefile>
+        <swi:sourcefile>(.*)[.][cC][pP]?[pP]?</swi:sourcefile>
         <swi:gcdafile>${1}.gcda</swi:gcdafile>
       </swi:indexer:gcov>
 
@@ -796,48 +796,57 @@
           The 'swi:print' section defines which messages should be printed
           to the log and to stderr stream. By analogy with the previous 
           configuration section, the flags are defined per modification status.
-          There are three types of messages which are configred by 
-          'swi:failures', 'swi:modifications' and 'swi:duplications' options.
+          There are 4 types of messages which are configred by 
+          'swi:failures', 'swi:modifications', 'swi:duplications' and 'swi:scanmessages' options.
           
-          (*) 'swi:failures'      - notifications about broken limits
-              'swi:modifications' - notes about added/modified/cloned/removed objects
-              'swi:duplications'  - pointers to the duplicated regions in files
-          (*) 'swi:scanmessages'  - messages collected by the internal scaner tool
-                                    (see 'swi:scaner' section above)
+          (*)  'swi:failures'      - notifications about broken limits
+                                     (see 'swi:limits' section below)
+                                     By default, these messages are activated
+               'swi:modifications' - notes about added/modified/cloned/removed objects
+                                     (see 'swi:xml/swi:baseline' option above
+                                     By default, these messages are activated
+          (**) 'swi:duplications'  - pointers to the duplicated regions in files
+                                     (see 'swi:indexer:dup' sections above)
+                                 (!) By default, these messages are NOT activated
+          (*)  'swi:scanmessages'  - messages collected by the internal scaner tool
+                                     (see 'swi:scaner' sections above)
+                                     By default, these messages are activated
           
-          (*) marks types of messages which affect the exit code (see 'swi:error' section above).
+          (*)  marks types of messages which affect the exit code (see 'swi:error' section above).
+          (**) these messages are always printed for an object if there failures for the index:
+               'swi:duplication/swi:symbols/swi:exact'
           
-          'swi:print' section can be missed. In this case all messages are activated by default.
+          'swi:print' section can be missed or empty. In this case default values are applied.
       -->
       <swi:print>
         <swi:added>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:added>
         <swi:removed>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:removed>
         <swi:modified>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:modified>
         <swi:cloned>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:cloned>
         <swi:unmodified>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:unmodified>
       </swi:print>
@@ -889,6 +898,19 @@
           <swi:notice>3</swi:notice>
           <swi:warning>1</swi:warning>
           
+          <!--
+              The next option is a regular expression.
+              If name of object which is under processing is mathced by this expression,
+              the limit is applied to this object.
+              Otherwise, the object is missed and the level becomes 'undefined' for the object.
+              
+              For example, value '^MY_PROJECT/MY_MODULE$' requires to apply the limit
+              to the module only, missing statistics for the project, files and functions.
+              
+              By default, statistics are validated for all objects.
+          -->
+          <swi:objectpattern>.*</swi:objectpattern>
+          
           <!--
               If some object is evaluated in non-regular level (info/notice/warning)
               and you consider that it is too excessive to fix it
@@ -952,6 +974,14 @@
             
             In this case it is necessary to limit 'swi:lines/swi:comment/swi:exact'
             (what we do here) in the relation with 'swi:lines/swi:executable/swi:exact'.
+            
+            Note: if statistic in the relation ('swi:lines/swi:executable/swi:exact'
+            in this example) is not defined OR equal to zero,
+            result depends on the sign of the limited statistic
+            ('swi:lines/swi:comment/swi:exact' in this example):
+                if statistic > 0 than relative statistic becomes 'Infinity'
+                if statistic < 0 than relative statistic becomes '-Infinity'
+                if statistic = 0 than relative statistic becomes equals to '1.00'
         -->
         <swi:exact swi:relation="swi:lines/swi:executable/swi:exact">
           <!-- 0.3  is 30% -->
@@ -1079,7 +1109,7 @@
         The following section defines the limitation for duplication index.
         In the example, it is required to control exact relative
         duplication index for functions and total relative
-        duplication index for files, modules and project.
+        duplication index for the whole project.
     -->
     <!-- STATISTIC-GROUP -->
     <swi:duplication>
@@ -1104,6 +1134,13 @@
           <swi:info>0.30</swi:info>
           <swi:notice>0.40</swi:notice>
           <swi:warning>0.60</swi:warning>
+          <!--
+              This option explicitly defines the content for validation.
+              It requires to apply the limit to the project and
+              miss modules, files and functions.
+          -->
+          <swi:objectpattern>^MY_PROJECT$</swi:objectpattern>
+          
           <!--
               Add here suppress section, if it is needed. For example:
               <swi:suppress>

+ 5 - 5
test/swi_config_ddd.xml

@@ -127,31 +127,31 @@
         <swi:added>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:added>
         <swi:removed>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:removed>
         <swi:modified>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:modified>
         <swi:cloned>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:cloned>
         <swi:unmodified>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:unmodified>
       </swi:print>