[SCM] Lisaac compiler branch, mildred-coverage-rebase, updated. lisaac-0.12-618-gd358222

Mildred Ki'Lya silkensedai at online.fr
Tue Mar 9 00:19:16 UTC 2010


The following commit has been merged in the mildred-coverage-rebase branch:
commit d358222b55bd588c5eb9ce8c2d070d5b05ca301d
Author: Mildred Ki'Lya <silkensedai at online.fr>
Date:   Tue Mar 9 01:12:42 2010 +0100

    Improved coverage
    
    - New optimized file format
    - File is written when the program exit only, and when running, it only updates
      data structures in memory (it just increment a number)
    - We can make a difference between dead code not compiled by Lisaac and code
      that did not run
    - HTML reports improved

diff --git a/src/any.li b/src/any.li
index bc593a1..5600ce3 100644
--- a/src/any.li
+++ b/src/any.li
@@ -230,7 +230,7 @@ Section Public
   - output_decl:STRING := STRING.create 60000;
   - output_glob:STRING := STRING.create 10000;
   - output_code:STRING := STRING.create 4_000_000;
-  - output_coverage:STRING := [ -? { is_coverage }; ] NULL;
+  - output_coverage:STRING := [ -? { is_coverage }; ] NULL; // TODO: Mildred: remove
 
   - title txt:STRING_CONSTANT in buf:STRING <-
   (
diff --git a/src/code_life/loop_end.li b/src/code_life/cov_instr.li
similarity index 56%
copy from src/code_life/loop_end.li
copy to src/code_life/cov_instr.li
index 8746cf3..a050fff 100644
--- a/src/code_life/loop_end.li
+++ b/src/code_life/cov_instr.li
@@ -20,72 +20,98 @@
 ///////////////////////////////////////////////////////////////////////////////
 Section Header
 
-  + name    := LOOP_END;
+  + name        := COV_INSTR;
 
-  - copyright   := "2003-2007 Benoit Sonntag";
+  - copyright   := "2010 Mildred Ki'Lya";
 
-
-  - author  := "Sonntag Benoit (bsonntag at loria.fr)";
-  - comment := "Loop end (call tail recursive).";
+  - author      := "Mildred Ki'Lya <http://ki.lya.online.fr>";
+  - comment     := "Coverage recorder instruction";
 
 Section Inherit
 
   + parent_instr:Expanded INSTR;
 
+Section Private
+
+  - next_seq_num :INTEGER := 0;
+
+  + seq_num :INTEGER := -1;
+
+  - all_coverage :FAST_ARRAY(COV_INSTR) := FAST_ARRAY(COV_INSTR).create 1024;
+
 Section Public
 
-  + loop:LOOP;
+  - lower :INTEGER <- 0;
+  - upper :INTEGER <- next_seq_num - 1;
+  - item i:INTEGER :COV_INSTR <-
+  ( + j :INTEGER;
+    + res :COV_INSTR;
+    j := all_coverage.lower;
+    {(j < all_coverage.upper) && {res = NULL}}.while_do {
+      (all_coverage.item j != NULL).if {
+        (all_coverage.item j.seq_num = i).if {
+          res := all_coverage.item j;
+        };
+      };
+      j := j + 1;
+    };
+    res
+  );
 
-  //
-  // Creation.
-  //
+  - count :INTEGER := 0;
 
-  - create p:POSITION loop l:LOOP :SELF <-
-  ( + result:SELF;
-    result := clone;
-    result.make p loop l;
-    result
+  + last_position :POSITION;
+
+  - set_last_position p:POSITION <-
+  (
+    last_position := p;
   );
 
-  - make p:POSITION loop l:LOOP <-
+  - create (p1, p2 :POSITION) :SELF <-
   (
-    position := p;
-    loop := l;
-    loop.set_link;
+    clone.make (p1, p2)
   );
 
-  - my_copy:SELF <-
+  - make (p1, p2 :POSITION) :SELF <-
   (
-    // Warning: See LOOP.my_copy
+    position := p1;
+    last_position := p2;
+    count := count + 1;
     Self
   );
 
   //
-  // Generation.
+  //
   //
 
-  - remove <-
-  (
-    loop.unset_link;
-  );
+  - my_copy:SELF <- Self;
+
+  //
+  // Execute.
+  //
+
+  - remove; // NOP
 
   - execute:INSTR <-
-  (
-    (list_current = loop.body).if {
-      POSITION.put_error semantic text "Recursivity without end (LOOP_END).";
-      loop.position.put_position;
-      position.put_position;
-      POSITION.send_error;
+  ( + result :INSTR;
+    is_coverage.if {
+      result := Self;
+    } else {
+      count := count - 1;
     };
+    result
+  );
 
-    ((is_optimization) && {loop_invariant = NULL} && {loop.link_count = 1}).if {
-      loop_invariant := loop;
+  - genere buffer:STRING <-
+  (
+    (seq_num = -1).if {
+      seq_num := next_seq_num;
+      next_seq_num := next_seq_num + 1;
+      all_coverage.add_last Self;
     };
-
-    seq_call_local_and_loop := seq_call_local_and_loop - 1;
-    seq_call_and_loop       := seq_call_and_loop - 1;
-    seq_inline := seq_inline + 1;
-    Self
+    buffer.append "++lisaac_coverage_table[";
+    seq_num.append_in buffer;
+    buffer.append "]";
   );
 
   //
@@ -94,20 +120,11 @@ Section Public
 
   - display buffer:STRING <-
   (
-    buffer.append "goto ";
-    buffer.append (loop.name);
-    display_ref buffer;
+    buffer.append "coverage";
   );
 
-  //
-  // Generation.
-  //
 
-  - genere buffer:STRING <-
-  (
-    buffer.append "goto ";
-    buffer.append (loop.name);
 
-    current_list_level := current_list_level - 1;
-  );
+
+
 
diff --git a/src/item/itm_list.li b/src/item/itm_list.li
index 3662544..279e6ca 100644
--- a/src/item/itm_list.li
+++ b/src/item/itm_list.li
@@ -51,6 +51,8 @@ Section Public
 
   - is_check_local:INTEGER;
 
+  + last_position :POSITION;
+
   //
   // Constructor
   //
@@ -88,6 +90,23 @@ Section Public
     code := c;
   );
 
+  - set_last_position p:POSITION <-
+  (
+    last_position := p;
+    ((is_coverage) && {! p.prototype.is_lip}).if {
+      (coverage_all_lists = NULL).if {
+        coverage_all_lists := FAST_ARRAY(POSITION).create 16192;
+      };
+      coverage_all_lists.add_last position;
+      coverage_all_lists.add_last p;
+    };
+  );
+
+Section LISAAC
+
+  - coverage_all_lists :FAST_ARRAY(POSITION) <-
+  ( coverage_all_lists := FAST_ARRAY(POSITION).create 16192 );
+
 Section Public
 
   - is_affect:POSITION <-
@@ -112,7 +131,7 @@ Section Public
   );
 
   - insert_code_coverage_hook last_position:POSITION in lst:FAST_ARRAY(ITM_CODE) <-
-  [
+  [ // TODO: Mildred: remove this slot
     -? { lst != NULL };
   ]
   (
@@ -171,6 +190,9 @@ Section Public
       };
     };
     // Append code.
+    is_coverage.if {
+      list_current.add_last (COV_INSTR.create (position, last_position));
+    };
     (code.lower).to (code.upper) do { j:INTEGER;
       i := code.item j.to_run;
       list_current.add_last i;
diff --git a/src/lisaac.li b/src/lisaac.li
index d35b931..6b31e4e 100644
--- a/src/lisaac.li
+++ b/src/lisaac.li
@@ -491,7 +491,7 @@ Section Private
       \} \n\n";
     };
     is_coverage.if {
-      buf.append "char *__Lisaac_proto_file_names[";
+      buf.append "char *__lisaac_proto_file_names[";
       buf.append (PROTOTYPE.prototype_list.count.to_string);
       buf.append "]={\n";
       (PROTOTYPE.prototype_list.lower).to (PROTOTYPE.prototype_list.upper-1) do {
@@ -506,15 +506,67 @@ Section Private
       buf.append (proto.filename);
       buf.append "\"\n};\n\n";
       title "CODE COVERAGE HOOKS" in buf;
+      buf.append "static int lisaac_coverage_block_info_length = ";
+      COV_INSTR.count.append_in output_code;
+      buf.append ";\nstatic struct { \n\
+        \  int proto_index;\n\
+        \  int start_line;\n\
+        \  int start_col;\n\
+        \  int stop_line;\n\
+        \  int stop_col;\n\
+        \} lisaac_coverage_block_info[";
+      COV_INSTR.count.append_in output_code;
+      buf.append "]={\n";
+      COV_INSTR.lower.to (COV_INSTR.upper) do { i:INTEGER;
+        + instr:COV_INSTR;
+        + p1, p2 :POSITION;
+        instr := COV_INSTR.item i;
+        (instr != NULL).if {
+          p1 := instr.position;
+          p2 := instr.last_position;
+          buf.append "  {";
+          p1.prototype.index.append_in buf;
+          buf.append ", ";
+          p1.line.append_in buf;
+          buf.append ", ";
+          p1.column.append_in buf;
+          buf.append ", ";
+          p2.line.append_in buf;
+          buf.append ", ";
+          p2.column.append_in buf;
+          buf.append "},\n";
+        } else {
+          buf.append "  {0, 0, 0, 0, 0} /* instr = NULL */,\n";
+        };
+      };
+      buf.remove_last 2;
+      buf.append "\n};\n\n";
       buf.append
-      "static void lisaac_coverage_hook(unsigned long start, unsigned long stop)\n\
-      \{\n\
-      \  fprintf (lisaac_coverage_file, \"COV:%d:%d:%d:%d:%s\\n\",\n\
-      \          start >> 17, (start >> 9) & 0xFF,\n\
-      \          stop  >> 17, (stop  >> 9) & 0xFF,\n\
-      \          __Lisaac_proto_file_names[start & 0x1FF]);\n\
-      \}\n\
-      \\n";
+        "static void lisaac_coverage_exit()\n\
+        \{\n\
+        \  int current_proto = -1;\n\
+        \  int i;\n\
+        \  \n\
+        \  \n\
+        \  FILE* f = fopen(lisaac_coverage_file, \"a\");\n\
+        \  for (i = 0; i < lisaac_coverage_block_info_length; ++i)\n\
+        \  {\n\
+        \    if (current_proto != lisaac_coverage_block_info[i].proto_index)\n\
+        \    {\n\
+        \      current_proto = lisaac_coverage_block_info[i].proto_index;\n\
+        \      fprintf (f, \"FILE:%s\\n\", __lisaac_proto_file_names[current_proto]);\n\
+        \    }\n\
+        \    fprintf (f, \"COVERAGE:%d:%d:%d:%d:%d\\n\",\n\
+        \      lisaac_coverage_table[i],\n\
+        \      lisaac_coverage_block_info[i].start_line,\n\
+        \      lisaac_coverage_block_info[i].start_col,\n\
+        \      lisaac_coverage_block_info[i].stop_line,\n\
+        \      lisaac_coverage_block_info[i].stop_col);\n\
+        \  }\n\
+        \  fflush(f);\n\
+        \  fclose(f);\n\
+        \}\n\
+        \\n";
     };
   );
 
@@ -663,6 +715,7 @@ Section Public
       };
       is_coverage.if {
         output_decl.append "#include <stdio.h>\n";
+        output_decl.append "#include <stdlib.h>\n";
       };
       output_decl.append
       "int arg_count;\n\
@@ -720,8 +773,13 @@ Section Public
     is_coverage.if {
       output_code.append "\
         \\n/* Code Coverage Hooks */\n\
-        \static FILE* lisaac_coverage_file = NULL;\n\
-        \static void lisaac_coverage_hook(unsigned long start, unsigned long stop);\n\
+        \static unsigned int  lisaac_coverage_table[";
+      COV_INSTR.count.append_in output_code;
+      output_code.append "];\n\
+        \static const char   *lisaac_coverage_file = \"";
+      output_code.append output_name;
+      output_code.append ".cov\";\n\
+        \static void lisaac_coverage_exit();\n\
         \\n";
     };
 
@@ -743,20 +801,17 @@ Section Public
     };
     output_code.append "{\n";
     is_coverage.if {
-      output_code.append "lisaac_coverage_file = fopen(\"";
-      output_code.append output_name;
-      output_code.append ".cov\", \"a\");\n";
-      output_code.append "  fprintf (lisaac_coverage_file, \"# COV:BEGIN_LINE:COL:END_LINE:COL:FILENAME\\n\");\n";
+      output_code.append
+       "  if (atexit(lisaac_coverage_exit)) {\n\
+       \    fprintf(stderr, \"cannot set code coverage exit function\\n\");\n\
+       \    exit(EXIT_FAILURE);\n\
+       \  }\n";
     };
     indent.append "  ";
 
     profil_current := NULL;
     list_main.genere_extern output_code;
 
-    is_coverage.if {
-      output_code.append "fflush(lisaac_coverage_file);\n";
-      output_code.append "fclose(lisaac_coverage_file);\n";
-    };
     (is_java).if_false {
       output_code.append "  return(0);\n";
     };
@@ -805,6 +860,32 @@ Section Public
     FS_MIN.close file_output;
 
     is_coverage.if {
+      + current_proto :PROTOTYPE;
+      + k:INTEGER;
+      string_tmp2.clear;
+      k := ITM_LIST.coverage_all_lists.lower;
+      {k < ITM_LIST.coverage_all_lists.upper}.while_do {
+        + p1, p2 :POSITION;
+        p1 := ITM_LIST.coverage_all_lists.item (k);
+        p2 := ITM_LIST.coverage_all_lists.item (k+1);
+        ? { p1.prototype = p2.prototype };
+        (p1.prototype != current_proto).if {
+          current_proto := p1.prototype;
+          string_tmp2.append "FILE:";
+          string_tmp2.append (current_proto.filename);
+          string_tmp2.add_last '\n';
+        };
+        string_tmp2.append "LIST:";
+        p1.line.append_in string_tmp2;
+        string_tmp2.add_last ':';
+        p1.column.append_in string_tmp2;
+        string_tmp2.add_last ':';
+        p2.line.append_in string_tmp2;
+        string_tmp2.add_last ':';
+        p2.column.append_in string_tmp2;
+        string_tmp2.add_last '\n';
+        k := k + 2;
+      };
       string_tmp.copy output_name;
       string_tmp.append ".cov";
       (! FS_MIN.make_file string_tmp).if {
@@ -814,7 +895,7 @@ Section Public
         die_with_code exit_failure_code;
       };
       f := FS_MIN.open_write string_tmp;
-      FS_MIN.write f with output_coverage size (output_coverage.count);
+      FS_MIN.write f with string_tmp2 size (string_tmp2.count);
       FS_MIN.close f;
     };
 
diff --git a/src/parser.li b/src/parser.li
index 1b62fcb..d526f08 100644
--- a/src/parser.li
+++ b/src/parser.li
@@ -1940,6 +1940,7 @@ Section Private
     + result_id:STRING_CONSTANT;
     + pos : POSITION;
 
+    read_space;
     pos := current_position; // Get the position before consuming the tokens
 
     (read_this_keyword (ALIAS_STR.variable_self)).if {
@@ -2086,7 +2087,7 @@ Section Private
       result.add_last e;
     };
     read_space;
-    last_group.insert_code_coverage_hook current_position in result;
+    last_group.set_last_position current_position;
     ALIAS_ARRAY(ITM_CODE).copy result
   );
 
@@ -2154,13 +2155,12 @@ Section Private
       }.do_while {continue};
 
       read_space;
-      pos := current_position;
+      result.set_last_position current_position;
 
       (! read_character ']').if {
 	warning_error (current_position,"Added ']'.");
       };
 
-      result.insert_code_coverage_hook pos in lst;
       e := ITM_PROTOTYPE.create current_position type (ITM_TYPE_SIMPLE.type_void);
       lst.add_last e;
       //
diff --git a/tools/licoverage b/tools/licoverage
index 0d81094..fde7115 100755
--- a/tools/licoverage
+++ b/tools/licoverage
@@ -130,13 +130,13 @@ my %all_starts;                 # Array of block id indexed by filename, start l
 my %all_stops;                  # Array of block id indexed by filename, stop line and column
 
 sub common_dir {
-    my $prefix = shift;
-    for (@_) {
-        while (! /^$prefix/) {
-          $prefix =~ s|/[^/]+/?$||;
-        }
+  my $prefix = shift;
+  for (@_) {
+    while (! /^$prefix/) {
+      $prefix =~ s|^(.*/)?[^/]+/?$|$1|;
     }
-    return $prefix;
+  }
+  return $prefix;
 }
 
 sub phtml {
@@ -166,6 +166,7 @@ sub new_block {
       'filename',       $proto_file,    # File name
       'id',             $id,            # File id (simple file name)
       'count',          0,              # How many blocks in the file
+      'living',         0,              # How many living blocks
       'covered',        0,              # How many covered blocks
       'blocks',         []              # List of all block ids
     }
@@ -182,7 +183,8 @@ sub new_block {
       'start',          [$start_line, $start_col],      # Start line and column
       'stop',           [$stop_line,  $stop_col],       # Stop line and column
       'filename',       $proto_file,                    # Proto filename
-      'count',          0                               # How many time executed
+      'count',          0,                              # How many time executed
+      'alive',          0                               # If the block is alive
     };
     $all_starts{$proto_file}[$start_line][$start_col] = $block_id;
     $all_stops {$proto_file}[$stop_line] [$stop_col]  = $block_id;
@@ -196,7 +198,16 @@ sub new_block {
   return $block_id;
 }
 
+sub is_excluded {
+  my ($file) = @_;
+  foreach my $exclude (@excludes) {
+    return 1 if ($file =~ m/$exclude/);
+  }
+  return 0;
+}
+
 sub process_files {
+  my $current_file;
   foreach my $filename (@_) {
     my $FILE;
     if ($filename ne '-') {
@@ -207,23 +218,55 @@ sub process_files {
     my $lineno=0;
     while (my $line = <$FILE>) {
       $lineno++;
+      unless ($lineno % 1000) {
+        print "...On the ${lineno}th line in $filename\n";
+      }
       next if substr($line, 0, 1) eq '#';
       chop $line;
       @_ = split(':', $line);
       my $line_type = shift @_;
-      if ($line_type eq "COV" or $line_type eq "CODE") {
+      if ($line_type eq "FILE") {
+        $current_file = join(':', @_);
+      } elsif ($line_type eq "LIST") {
         my $start_line = shift @_;
         my $start_col  = shift @_;
         my $stop_line  = shift @_;
         my $stop_col   = shift @_;
-        my $proto_file = join(':', @_);
-        my $skip       = 0;
-        foreach my $exclude (@excludes) {
-          $skip = ($proto_file =~ m/$exclude/);
+        my $proto_file = $current_file;
+        next if is_excluded ($proto_file);
+        my $block_id = new_block($start_line, $start_col, $stop_line, $stop_col, $proto_file);
+      } elsif ($line_type eq "COVERAGE") {
+        my $cov_count  = shift @_;
+        my $start_line = shift @_;
+        my $start_col  = shift @_;
+        my $stop_line  = shift @_;
+        my $stop_col   = shift @_;
+        my $proto_file = $current_file;
+        next if is_excluded ($proto_file);
+        my $block_id = new_block($start_line, $start_col, $stop_line, $stop_col, $proto_file);
+        if (not $all_blocks{$block_id}->{alive}) {
+          $all_blocks{$block_id}->{alive} = 1;
+          $all_files{$proto_file}->{living}++;
+        }
+        if ($cov_count) {
+          if (not $all_blocks{$block_id}->{count}) {
+            $all_files{$proto_file}->{covered}++;
+          }
+          $all_blocks{$block_id}->{count} += $cov_count;
         }
-        next if $skip;
+      } elsif ($line_type eq "COV" or $line_type eq "CODE") {
+        my $start_line = shift @_;
+        my $start_col  = shift @_;
+        my $stop_line  = shift @_;
+        my $stop_col   = shift @_;
+        my $proto_file = join(':', @_);
+        next if is_excluded ($proto_file);
         my $block_id = new_block($start_line, $start_col, $stop_line, $stop_col, $proto_file);
         if ($line_type eq "COV") {
+          if (not $all_blocks{$block_id}->{alive}) {
+            $all_blocks{$block_id}->{alive} = 1;
+            $all_files{$proto_file}->{living}++;
+          }
           if (not $all_blocks{$block_id}->{count}) {
             $all_files{$proto_file}->{covered}++;
           }
@@ -250,11 +293,15 @@ sub generate_html {
   while (my ($id, $file) = each(%all_files)) {
     my $html_file = "coverage_".$file->{id}.".html";
     $vars_index->{files}->[$i++] = {
-      shortname         => phtml(substr($file->{filename}, length($common_dir)+1)),
-      block_count       => $file->{count},
-      block_covered     => $file->{covered},
-      percent_covered   => sprintf("% 3.2f", 100 * $file->{covered}/$file->{count}),
-      url               => phtml($html_file)
+      shortname              => phtml(substr($file->{filename}, length($common_dir))),
+      block_count            => $file->{count},
+      block_living           => $file->{living},
+      block_covered          => $file->{covered},
+      block_dead             => $file->{count} - $file->{living},
+      percent_covered        => sprintf("% 3.2f", $file->{count}  ? (100 * $file->{covered}/$file->{count})  : 100),
+      percent_covered_living => sprintf("% 3.2f", $file->{living} ? (100 * $file->{covered}/$file->{living}) : 0),
+      percent_covered_dead   => sprintf("% 3.2f", $file->{count}  ? (100 * ($file->{count} - $file->{living})/$file->{count}) : 0),
+      url                    => phtml($html_file)
     };
     open SRC, '<', $file->{filename};
     my $source_code;
@@ -263,19 +310,32 @@ sub generate_html {
       $lineno++;
       my @characters = split //, $line;
       my $colno = 0;
+      $source_code .= '<br /><span lineno="'.$lineno.'"></span>';
       foreach my $char (@characters) {
         my $stop  = $all_stops {$file->{filename}}[$lineno][$colno];
         my $start = $all_starts{$file->{filename}}[$lineno][$colno];
+        my $after = "";
         if ($start){
           my @classes = ('block');
+          my $extra = "";
           if ($all_blocks{$start}->{count}) {
             $classes[@classes] = 'covered';
-          } else {
+            $after='<span coveragecount="'.$all_blocks{$start}->{count}.'"></span>';
+          } elsif ($all_blocks{$start}->{alive}) {
             $classes[@classes] = 'not-covered';
+          } else {
+            $classes[@classes] = 'dead';
           }
-          $source_code .= '<span class="'.join(' ', @classes).'">'
+          $source_code .= '<span class="'.join(' ', @classes).'"'.$extra.'>'
+        }
+        if ($char eq ' ') {
+          $source_code .= "&nbsp;";
+        } elsif ($char eq "\t") {
+          $source_code .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
+        } else {
+          $source_code .= phtml($char);
         }
-        $source_code .= phtml($char);
+        $source_code .= $after;
         if ($stop){
           $source_code .= '</span>'
         }
@@ -301,7 +361,7 @@ sub generate_html {
 sub generate_summary {
   while (my ($id, $file) = each(%all_files)) {
     my $proto_file = $file->{filename};
-    print substr($proto_file, length($common_dir)+1);
+    print substr($proto_file, length($common_dir));
     my $percent = 100 * $file->{covered}/$file->{count};
     printf(": % 3.2f%% covered", $percent);
     print " ($file->{covered}/$file->{count})\n"
@@ -356,18 +416,33 @@ __END__
       <thead>
         <tr>
           <th>File</th>
-          <th colspan="6">Coverage</th>
+          <th colspan="5">Whole Code Coverage</th>
+          <th colspan="5">Living Code Coverage</th>
+          <th colspan="5">Dead code</th>
         </tr>
       </thead>
       <tbody>
 [% FOREACH file IN files %]
         <tr>
           <td><a href="[% file.url %]">[% file.shortname %]</a></td>
+          <!-- whole code -->
           <td class="numeric">[% file.percent_covered %]%</td>
           <td><div class="progressbar"><div style="width: [% file.percent_covered %]px;"></div></div></td>
-          <td class="left">[% file.block_covered %]</td>
+          <td class="right">[% file.block_covered %]</td>
+          <td>/</td>
+          <td class="left">[% file.block_count %]</td>
+          <!-- living code -->
+          <td class="numeric">[% file.percent_covered_living %]%</td>
+          <td><div class="progressbar"><div style="width: [% file.percent_covered_living %]px;"></div></div></td>
+          <td class="right">[% file.block_covered %]</td>
+          <td>/</td>
+          <td class="left">[% file.block_living %]</td>
+          <!--  dead code -->
+          <td class="numeric">[% file.percent_covered_dead %]%</td>
+          <td><div class="progressbar"><div style="width: [% file.percent_covered_dead %]px;"></div></div></td>
+          <td class="right">[% file.block_dead %]</td>
           <td>/</td>
-          <td class="right">[% file.block_count %]</td>
+          <td class="left">[% file.block_count %]</td>
         </tr>
 [% END %]
       </tbody>
@@ -385,15 +460,38 @@ __END__
     <title>Code coverage for [% shortname %]</title>
     <style>
       .covered {
+        background-color: palegreen;
+      }
+      [coveragecount]:before {
+        font-size: 0.7em;
+        padding-left: 0.25em;
+        padding-right: 0.25em;
+        vertical-align: middle;
+        content: attr(coveragecount);
         background-color: lightgreen;
+        border: solid thin darkgreen;
+        -moz-border-radius: 0.25em;
+      }
+      [lineno]:after {
+        content: attr(lineno) ": ";
+        color: grey;
+        display: block;
+        float: left;
+        width: 5em;
+        text-align: right;
+        vertical-align: bottom;
+        padding-right: .5em;
       }
       .not-covered {
-        background-color: coral;
+        background-color: tomato;
+      }
+      .dead {
+        background-color: lightgrey;
       }
     </style>
   </head>
   <body>
     <h1>Code coverage for [% shortname %]</h1>
-    <pre>[% code %]</pre>
+    <code>[% code %]</code>
   </body>
 </html>
\ No newline at end of file

-- 
Lisaac compiler



More information about the Lisaac-commits mailing list