Pārlūkot izejas kodu

-- 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 gadi atpakaļ
vecāks
revīzija
3686184b35
7 mainītis faili ar 349 papildinājumiem un 199 dzēšanām
  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
        -- Date:         2010/02/12
           Reference:    noref
           Reference:    noref

+ 166 - 125
lib/SWI/Appraiser.pm

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

+ 33 - 22
lib/SWI/Converter.pm

@@ -199,6 +199,7 @@ sub swiNotificationPrint
     }
     }
 
 
     # Print 'swi:failures'
     # Print 'swi:failures'
+    my $areThereDupViolations = 0;
     foreach my $keyStat ( keys %$objStat )
     foreach my $keyStat ( keys %$objStat )
     {
     {
         my $subStat = $objStat->{$keyStat};
         my $subStat = $objStat->{$keyStat};
@@ -241,33 +242,14 @@ sub swiNotificationPrint
                         eq "on" )
                         eq "on" )
                     {
                     {
                         print $file $notification;
                         print $file $notification;
+                        print $file "\n";
 
 
-                        # Print 'swi:duplications'
                         if (   $keyStat eq "swi:duplication"
                         if (   $keyStat eq "swi:duplication"
                             && $keySubStat eq "swi:symbols"
                             && $keySubStat eq "swi:symbols"
-                            && $config->{"swi:report"}->{"swi:notifications"}
+                            && $type       eq 'swi:exact' )
-                            ->{"swi:print"}->{ "swi:" . $objDiff }
-                            ->{"swi:duplications"} eq "on" )
                         {
                         {
-                            die('Internal Error occured!')
+                            $areThereDupViolations = 1;
-                              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";
-                                }
-                            }
                         }
                         }
-                        print $file "\n";
                     }
                     }
 
 
                     if ( $config->{"swi:report"}->{"swi:notifications"}
                     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'
     # Print 'swi:scanmessages'
     if ( $config->{"swi:report"}->{"swi:notifications"}->{"swi:print"}
     if ( $config->{"swi:report"}->{"swi:notifications"}->{"swi:print"}
         ->{ "swi:" . $objDiff }->{"swi:scanmessages"} eq "on" )
         ->{ "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'}
         $config->{'swi:report'}->{'swi:notifications'}->{'swi:print'}
-          ->{$modType}->{'swi:duplications'} = 'on';
+          ->{$modType}->{'swi:duplications'} = 'off';
     }
     }
     if (
     if (
         !defined(
         !defined(

+ 56 - 26
lib/SWI/Processor.pm

@@ -204,9 +204,13 @@ sub swiProcess
         $dupindexHandler =
         $dupindexHandler =
           open3( $dupindexIn, $dupindexOut, $dupindexErr,
           open3( $dupindexIn, $dupindexOut, $dupindexErr,
             "$rootLocation/dupindex/bin/dupindex.exe" );
             "$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 =
         my $dupfinderSettings =
@@ -655,16 +659,21 @@ sub swiSourceIndexAdd
     {
     {
         my $function = $functionsData->{$functionName};
         my $function = $functionsData->{$functionName};
 
 
-        my $block = {};
+        my $block       = {};
+        my $blockOffset = {};
+
+        # Initialize function name
         $block->{'functionname'} = $functionName;
         $block->{'functionname'} = $functionName;
         $block->{'functionname'} =~
         $block->{'functionname'} =~
 s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeContainerDelimeter)*($regexpCodeFunctionIdentifier)/$3/;
 s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeContainerDelimeter)*($regexpCodeFunctionIdentifier)/$3/;
+        $blockOffset->{'functionname'} = $function->{'swi:line:headerstart'};
 
 
         if ( $functionName ne $regexpCodeGlobalFunctionName )
         if ( $functionName ne $regexpCodeGlobalFunctionName )
         {
         {
 
 
             # Get content
             # Get content
-            $block->{'initial'} = "";
+            $block->{'initial'}       = "";
+            $blockOffset->{'initial'} = $function->{'swi:line:commentstart'};
             for (
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -673,7 +682,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
             {
                 $block->{'initial'} .= $block_Initial[$i] . "\n";
                 $block->{'initial'} .= $block_Initial[$i] . "\n";
             }
             }
-            $block->{'code'} = "";
+            $block->{'code'}       = "";
+            $blockOffset->{'code'} = $function->{'swi:line:commentstart'};
             for (
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -682,7 +692,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
             {
                 $block->{'code'} .= $block_Code[$i] . "\n";
                 $block->{'code'} .= $block_Code[$i] . "\n";
             }
             }
-            $block->{'comments'} = "";
+            $block->{'comments'}       = "";
+            $blockOffset->{'comments'} = $function->{'swi:line:commentstart'};
             for (
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -691,7 +702,9 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
             {
                 $block->{'comments'} .= $block_Comment[$i] . "\n";
                 $block->{'comments'} .= $block_Comment[$i] . "\n";
             }
             }
-            $block->{'nopreprocessor'} = "";
+            $block->{'nopreprocessor'}       = "";
+            $blockOffset->{'nopreprocessor'} =
+              $function->{'swi:line:commentstart'};
             for (
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -700,7 +713,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
             {
             {
                 $block->{'nopreprocessor'} .= $block_NoPrep[$i] . "\n";
                 $block->{'nopreprocessor'} .= $block_NoPrep[$i] . "\n";
             }
             }
-            $block->{'nostrings'} = "";
+            $block->{'nostrings'}       = "";
+            $blockOffset->{'nostrings'} = $function->{'swi:line:commentstart'};
             for (
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i <= $function->{'swi:line:blockend'} ;
                 $i <= $function->{'swi:line:blockend'} ;
@@ -716,7 +730,10 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                   $function->{'swi:pos:headerstart'}
                   $function->{'swi:pos:headerstart'}
               )
               )
               . "\n";
               . "\n";
-            $block->{'commentshead'} = "";
+            $blockOffset->{'purified'} = $function->{'swi:line:headerstart'};
+            $block->{'commentshead'}   = "";
+            $blockOffset->{'commentshead'} =
+              $function->{'swi:line:commentstart'};
             for (
             for (
                 my $i = $function->{'swi:line:commentstart'} ;
                 my $i = $function->{'swi:line:commentstart'} ;
                 $i < $function->{'swi:line:headerstart'} ;
                 $i < $function->{'swi:line:headerstart'} ;
@@ -726,7 +743,6 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                 $block->{'commentshead'} .= $block_Comment[$i] . "\n";
                 $block->{'commentshead'} .= $block_Comment[$i] . "\n";
             }
             }
 
 
-            # functionname created above
             $block->{'functionhead'} = substr(
             $block->{'functionhead'} = substr(
                 $block_Purified,
                 $block_Purified,
                 $function->{'swi:pos:headerstart'},
                 $function->{'swi:pos:headerstart'},
@@ -734,6 +750,8 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                   $function->{'swi:pos:headerstart'}
                   $function->{'swi:pos:headerstart'}
               )
               )
               . "\n";
               . "\n";
+            $blockOffset->{'functionhead'} =
+              $function->{'swi:line:headerstart'};
             $block->{'functionbody'} = substr(
             $block->{'functionbody'} = substr(
                 $block_Purified,
                 $block_Purified,
                 $function->{'swi:pos:blockstart'},
                 $function->{'swi:pos:blockstart'},
@@ -741,25 +759,37 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                   $function->{'swi:pos:blockstart'}
                   $function->{'swi:pos:blockstart'}
               )
               )
               . "\n";
               . "\n";
+            $blockOffset->{'functionbody'} = $function->{'swi:line:blockstart'};
         }
         }
         else
         else
         {
         {
             $block->{'initial'} =
             $block->{'initial'} =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Initial );
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Initial );
-            $block->{'code'} =
+            $blockOffset->{'initial'} = 0;
+            $block->{'code'}          =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Code );
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Code );
-            $block->{'comments'} =
+            $blockOffset->{'code'} = 0;
+            $block->{'comments'}   =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Comment );
               swiSourceCodeGlobalGet( $functionsData, undef, @block_Comment );
+            $blockOffset->{'comments'} = 0;
             $block->{'nopreprocessor'} =
             $block->{'nopreprocessor'} =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_NoPrep );
               swiSourceCodeGlobalGet( $functionsData, undef, @block_NoPrep );
-            $block->{'nostrings'} =
+            $blockOffset->{'nopreprocessor'} = 0;
+            $block->{'nostrings'}            =
               swiSourceCodeGlobalGet( $functionsData, undef, @block_NoStr );
               swiSourceCodeGlobalGet( $functionsData, undef, @block_NoStr );
-            $block->{'purified'} =
+            $blockOffset->{'nostrings'} = 0;
+            $block->{'purified'}        =
               swiSourceCodeGlobalGet( $functionsData, undef, $block_Purified );
               swiSourceCodeGlobalGet( $functionsData, undef, $block_Purified );
-            $block->{'commentshead'} =
+            $blockOffset->{'purified'} = 0;
+            $block->{'commentshead'}   =
               swiSourceCodeGlobalGet( $functionsData,
               swiSourceCodeGlobalGet( $functionsData,
                 $function->{'swi:line:headerstart'},
                 $function->{'swi:line:headerstart'},
                 @block_Comment );
                 @block_Comment );
+            $blockOffset->{'commentshead'} = 0;
+            $block->{'functionhead'}       = "";    # N/A
+            $blockOffset->{'functionhead'} = 0;
+            $block->{'functionbody'}       = "";    # N/A
+            $blockOffset->{'functionbody'} = 0;
         }
         }
 
 
         # Initialize container
         # Initialize container
@@ -793,12 +823,12 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
         # Note: this statistic is used to detect differences
         # Note: this statistic is used to detect differences
         # Global code is compared without new lines
         # Global code is compared without new lines
         my $initialContent = $block->{'initial'};
         my $initialContent = $block->{'initial'};
-        if ($functionName eq $regexpCodeGlobalFunctionName)
+        if ( $functionName eq $regexpCodeGlobalFunctionName )
         {
         {
             $initialContent =~ s/\n+//g;
             $initialContent =~ s/\n+//g;
         }
         }
         $function->{'swi:statistic'}->{'swi:length'}->{'swi:source'}
         $function->{'swi:statistic'}->{'swi:length'}->{'swi:source'}
-          ->{'swi:exact'} = length( $initialContent );
+          ->{'swi:exact'} = length($initialContent);
 
 
         # Calculate swi:length->swi:executable
         # Calculate swi:length->swi:executable
         $function->{'swi:statistic'}->{'swi:length'}->{'swi:executable'}
         $function->{'swi:statistic'}->{'swi:length'}->{'swi:executable'}
@@ -882,7 +912,7 @@ s/($regexpCodeContainerDelimeter)?($regexpCodeContainerIdentifier$regexpCodeCont
                     @{ $function->{'swi:reference'} },
                     @{ $function->{'swi:reference'} },
                     swiSourceCodeScan(
                     swiSourceCodeScan(
                         $file,
                         $file,
-                        $function->{'swi:line:headerstart'},
+                        $blockOffset->{ $rule->{'swi:codecontent'} },
                         $block->{ $rule->{'swi:codecontent'} },
                         $block->{ $rule->{'swi:codecontent'} },
                         $rule->{'swi:searchpattern'},
                         $rule->{'swi:searchpattern'},
                         $rule->{'swi:messagepattern'}
                         $rule->{'swi:messagepattern'}
@@ -1014,14 +1044,16 @@ sub swiSourceIndexGcovAdd
     my $fh = new FileHandle( $location . "/" . $gcdaFile, "r" );
     my $fh = new FileHandle( $location . "/" . $gcdaFile, "r" );
     if ( !defined($fh) )
     if ( !defined($fh) )
     {
     {
-        STATUS("gcda file is not found '$location/$gcdaFile'.");
+        STATUS("gcda file '$location/$gcdaFile' is not found  for the '$file' source.");
     }
     }
     else
     else
     {
     {
         my $gcovCommand = 'gcov -f -b $location/$gcdaFile';
         my $gcovCommand = 'gcov -f -b $location/$gcdaFile';
-        STATUS("Calling command '$gcovCommand'...");
+        
-
         my $gcovData = `$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 );
         my @covData  = split( "\n\n", $gcovData );
 
 
         foreach (@covData)
         foreach (@covData)
@@ -1063,9 +1095,6 @@ m/^Function\s+\'(.*)\'\s+Lines\s+executed:(.*)%\s+of\s+(.*)\s+Branches\s+execute
             else
             else
             {
             {
                 STATUS(
                 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"
 "gcov reports the data for '$functionName' function but SWI parser did not detect it"
                 );
                 );
                 $exitCode++;
                 $exitCode++;
@@ -1156,8 +1185,9 @@ m/^($regexpCodeFunctionModifier)*($regexpCodeFunctionIdentifier)($regexpCodeFunc
                     # Remove empty symbols in identifier
                     # Remove empty symbols in identifier
                     $word =~ s/\s+$//;
                     $word =~ s/\s+$//;
                     $word =~ s/[\n\t ]+/ /g;
                     $word =~ s/[\n\t ]+/ /g;
-                    $word =~ s/\s*$regexpCodeContainerDelimeter\s*/$regexpCodeContainerDelimeter/;
+                    $word =~
-                    
+s/\s*$regexpCodeContainerDelimeter\s*/$regexpCodeContainerDelimeter/;
+
                     # Remove empty symbols in modifier
                     # Remove empty symbols in modifier
                     $mod =~ s/^\s*//;
                     $mod =~ s/^\s*//;
                     $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
               which is interpolated before: variables ${1}, ${2}, ... are replaced by actual strings
               from 'swi:searchpattern' regexp hooks.
               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:replacepattern>${1}int ${2}(unsigned int stateId, unsigned int eventId, struct EVENT_DATA_TYPE eventData)</swi:replacepattern>
         </swi:rule>
         </swi:rule>
         <!--
         <!--
@@ -640,7 +640,7 @@
             
             
             By default, all files are affected.
             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.
             The coverage statistic is avaialble in 'gcda' files.
             gcov tool reads these files and reports the information.
             gcov tool reads these files and reports the information.
@@ -662,14 +662,14 @@
             
             
             The example below demostrates the case of mapping:
             The example below demostrates the case of mapping:
                  from 'file.c' to 'file.gcda'
                  from 'file.c' to 'file.gcda'
-                 from 'otehrfile.h' to 'otherfile.gcda'
+                 from 'otehrfile.c' to 'otherfile.gcda'
                  and so on...
                  and so on...
             
             
             If the 'gcda' file is not found, coverage statistic is not collected and not reported.
             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:gcdafile>${1}.gcda</swi:gcdafile>
       </swi:indexer:gcov>
       </swi:indexer:gcov>
 
 
@@ -796,48 +796,57 @@
           The 'swi:print' section defines which messages should be printed
           The 'swi:print' section defines which messages should be printed
           to the log and to stderr stream. By analogy with the previous 
           to the log and to stderr stream. By analogy with the previous 
           configuration section, the flags are defined per modification status.
           configuration section, the flags are defined per modification status.
-          There are three types of messages which are configred by 
+          There are 4 types of messages which are configred by 
-          'swi:failures', 'swi:modifications' and 'swi:duplications' options.
+          'swi:failures', 'swi:modifications', 'swi:duplications' and 'swi:scanmessages' options.
           
           
-          (*) 'swi:failures'      - notifications about broken limits
+          (*)  'swi:failures'      - notifications about broken limits
-              'swi:modifications' - notes about added/modified/cloned/removed objects
+                                     (see 'swi:limits' section below)
-              'swi:duplications'  - pointers to the duplicated regions in files
+                                     By default, these messages are activated
-          (*) 'swi:scanmessages'  - messages collected by the internal scaner tool
+               'swi:modifications' - notes about added/modified/cloned/removed objects
-                                    (see 'swi:scaner' section above)
+                                     (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:print>
         <swi:added>
         <swi:added>
           <swi:failures>on</swi:failures>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:added>
         </swi:added>
         <swi:removed>
         <swi:removed>
           <swi:failures>on</swi:failures>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:removed>
         </swi:removed>
         <swi:modified>
         <swi:modified>
           <swi:failures>on</swi:failures>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:modified>
         </swi:modified>
         <swi:cloned>
         <swi:cloned>
           <swi:failures>on</swi:failures>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:cloned>
         </swi:cloned>
         <swi:unmodified>
         <swi:unmodified>
           <swi:failures>on</swi:failures>
           <swi:failures>on</swi:failures>
           <swi:modifications>off</swi:modifications>
           <swi:modifications>off</swi:modifications>
-          <swi:duplications>on</swi:duplications>
+          <swi:duplications>off</swi:duplications>
           <swi:scanmessages>on</swi:scanmessages>
           <swi:scanmessages>on</swi:scanmessages>
         </swi:unmodified>
         </swi:unmodified>
       </swi:print>
       </swi:print>
@@ -889,6 +898,19 @@
           <swi:notice>3</swi:notice>
           <swi:notice>3</swi:notice>
           <swi:warning>1</swi:warning>
           <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)
               If some object is evaluated in non-regular level (info/notice/warning)
               and you consider that it is too excessive to fix it
               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'
             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'.
             (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">
         <swi:exact swi:relation="swi:lines/swi:executable/swi:exact">
           <!-- 0.3  is 30% -->
           <!-- 0.3  is 30% -->
@@ -1079,7 +1109,7 @@
         The following section defines the limitation for duplication index.
         The following section defines the limitation for duplication index.
         In the example, it is required to control exact relative
         In the example, it is required to control exact relative
         duplication index for functions and total relative
         duplication index for functions and total relative
-        duplication index for files, modules and project.
+        duplication index for the whole project.
     -->
     -->
     <!-- STATISTIC-GROUP -->
     <!-- STATISTIC-GROUP -->
     <swi:duplication>
     <swi:duplication>
@@ -1104,6 +1134,13 @@
           <swi:info>0.30</swi:info>
           <swi:info>0.30</swi:info>
           <swi:notice>0.40</swi:notice>
           <swi:notice>0.40</swi:notice>
           <swi:warning>0.60</swi:warning>
           <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:
               Add here suppress section, if it is needed. For example:
               <swi:suppress>
               <swi:suppress>

+ 5 - 5
test/swi_config_ddd.xml

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