bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Project management and code quality tools


From: Simon Josefsson
Subject: Project management and code quality tools
Date: Tue, 07 Oct 2008 09:36:01 +0200
User-agent: Gnus/5.110011 (No Gnus v0.11) Emacs/22.2 (gnu/linux)

address@hidden writes:

>    > I'm also interested in similar services, it would be great to integrate
>    > them with my http://josefsson.org/autobuild/ project.
>
>    I am designing (no time left at the moment so progress is slow) a system
>    to, in a structured way, do some softwares that can be called something
>    like autotest. I want to have:
>      coveragre with gcov (using lcov)
>       profiling with gprof
>    and the results printed to html.
>
>    Also I would like
>      mem check
>      statical analysis (either with pedantic flags or some *lint tool).
>
>    Has any one seen a tool that does this?
>
> In the GNU PDF project we are using some ad-hoc scripts to achieve
> some degree of "continuous integration". You can find the result in
> http://www.gnupdf.org/Library, sections "quality" and
> "documentation". The scripts generating all the stuff are in the
> 'prmgt/' directory in the libgnupdf sources distribution.

I have taken a closer look at your prmgt/ directory, and I really like
your efforts.  I want to use this in my projects, and the simplest for
me would be to move some of your scripts into gnulib.  What are your
thoughts on that?

To see what I mean, an example may be useful.  The cyclomatic code
complexity tables appears to be a simple start, so below is a gnulib
module for it, based on your code in prmgt/ in gnupdf.

Output for libidn is available from:
http://www.gnu.org/software/libidn/cyclo/libidn-cyclo.html

This was generated using a small Makefile.am snippet in libidn:

libidn-cyclo.html:
        $(PMCCABE) ${top_srcdir}/lib/*.[ch] \
                | sort -nr \
                | $(AWK) -f ${top_srcdir}/build-aux/pmccabe2html \
                        -v lang=html -v name="$(PACKAGE_NAME)" \
                        -v 
vcurl="http://git.savannah.gnu.org/gitweb/?p=libidn.git;a=blob;f=%FILENAME%;hb=HEAD";
 \
                        -v url="http://www.gnu.org/software/libidn/"; \
                        -v css="${top_srcdir}/build-aux/pmccabe.css" \
                        > tmp
        mv tmp libidn-cyclo.html

Thoughts from the gnulib crowd appreciated as well.

My next step is to propose a gnulib module for code coverage testing
(lcov output) as well, or at least look into if that is a feasible
approach.

/Simon

>From 7301ffa106d3b478030607ca1d83b74531468506 Mon Sep 17 00:00:00 2001
From: Simon Josefsson <address@hidden>
Date: Tue, 7 Oct 2008 09:24:34 +0200
Subject: [PATCH] Add pmccabe2html module, from gnupdf.

---
 ChangeLog              |    8 +
 build-aux/pmccabe.css  |  227 ++++++++++++
 build-aux/pmccabe2html |  888 ++++++++++++++++++++++++++++++++++++++++++++++++
 m4/pmccabe2html.m4     |   14 +
 modules/pmccabe2html   |   23 ++
 5 files changed, 1160 insertions(+), 0 deletions(-)
 create mode 100644 build-aux/pmccabe.css
 create mode 100755 build-aux/pmccabe2html
 create mode 100644 m4/pmccabe2html.m4
 create mode 100644 modules/pmccabe2html

diff --git a/ChangeLog b/ChangeLog
index f1c32e6..532fa3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-10-07  Simon Josefsson  <address@hidden>
+
+       Add pmccabe2html module, from gnupdf.
+       * build-aux/pmccabe.css: New file.
+       * build-aux/pmccabe2html: New file.
+       * m4/pmccabe2html.m4: New file.
+       * modules/pmccabe2html: New file.
+
 2008-10-07  Richard W.M. Jones <address@hidden>
 
        flock: new module
diff --git a/build-aux/pmccabe.css b/build-aux/pmccabe.css
new file mode 100644
index 0000000..2d94c91
--- /dev/null
+++ b/build-aux/pmccabe.css
@@ -0,0 +1,227 @@
+body {
+
+    font-family: Helvetica, sans-serif;
+
+}
+
+.page_title {
+
+    font: 18pt Georgia, serif;
+/*    font-size: 1.5em;
+    font-weight: bold; */
+    color: darkred;
+    border-bottom: 2px solid darkred;
+}
+
+.section_title {
+
+    font: 14pt Georgia, serif;
+    color: darkred;
+    border-bottom: 2px dashed darkred;
+}
+
+.report_timestamp {
+
+    color: darkred;
+    font-weight: bold;
+
+}
+
+.function_src {
+
+    text-align: left;
+    background: white;
+}
+
+.resume_table {
+
+}
+
+.resume_header_entry {
+    
+    color: black;
+}
+
+.resume_number_entry {
+
+    color: darkred;
+    font-weight: bold;
+    text-align: right;
+}
+
+.ranges_table {
+
+    border-spacing: 0px;
+    border-bottom: solid 2px black;
+    border-top: solid 2px black;
+    border-left: solid 2px black;
+    border-right: solid 2px black;
+}
+
+.ranges_header_entry {
+
+    padding: 5px;
+    border-bottom: solid 1px black;
+    font-size: 1em;
+    font-weight: bold;
+    color: darkred;
+    text-align: left;
+}
+
+.ranges_entry {
+
+}
+
+.ranges_entry_simple {
+
+    background: #87ff75; 
+
+}
+
+.ranges_entry_moderate {
+
+    background: #fffc60;
+
+}
+
+.ranges_entry_high {
+
+    background: #ff5a5d;
+
+}
+
+.ranges_entry_untestable {
+
+    background: #993300
+
+}
+
+
+.function_table {
+
+    border-spacing: 0px;
+    border-bottom: solid 2px black;
+    border-top: solid 2px black;
+    border-left: solid 2px black;
+    border-right: solid 2px black;
+}
+
+.function_table_caption {
+
+    font-size: 1.1em;
+    font-weight: bold;
+    color: black;
+    padding: 5px;
+}
+
+.function_table_header {
+    
+}
+
+
+.function_table_header_entry {
+
+    padding: 5px;
+    border-bottom: solid 1px black;
+    font-size: 1em;
+    font-weight: bold;
+    color: darkred;
+    text-align: left;
+}
+
+.function_entry {
+
+
+}
+
+
+.function_entry_simple {
+
+    background: #87ff75; 
+
+}
+
+.function_entry_moderate {
+
+    background: #fffc60;
+
+}
+
+.function_entry_high {
+
+    background: #ff5a5d;
+
+}
+
+.function_entry_untestable {
+
+    background: #993300
+
+}
+
+
+.function_entry_name {
+
+    font-size: 1em;
+    text-align: left;
+    font-weight: bold;
+    text-valign: top;
+
+    border-top: solid 1px black;
+    padding: 3px;
+}
+
+.function_entry_cyclo {
+
+    font-size: 1em;
+    text-align: right;
+    text-valign: top;
+
+    border-top: solid 1px black;
+    padding: 3px;
+}
+
+.function_entry_number {
+
+    font-size: 1em;
+    text-align: right;
+    text-valign: top;
+
+    border-top: solid 1px black;
+    padding: 3px;
+}
+
+.function_entry_filename {
+
+    font-size: 1em;
+    text-align: left;
+    text-valign: top;
+
+    border-top: solid 1px black;
+    padding: 3px;
+}
+
+.sidemenu {
+    
+    border: 1px black solid;
+    padding: 5px;
+
+}
+
+.sidemenuheader {
+ 
+    color: darkred;
+    font-size: 1.1em;
+    font-weight: bold;
+    border-bottom: 1px dashed darkred;
+}
+
+.sidemenuentry {
+
+
+}
+
+.menu {
+
+}
+
diff --git a/build-aux/pmccabe2html b/build-aux/pmccabe2html
new file mode 100755
index 0000000..03e697b
--- /dev/null
+++ b/build-aux/pmccabe2html
@@ -0,0 +1,888 @@
+#!/usr/bin/awk -f
+# pmccabe2html - pmccabe to html converter
+
+# Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Written by Jose E. Marchesi <address@hidden>.
+# Adapted for gnulib by Simon Josefsson <address@hidden>.
+
+# Typical Invocation is from a Makefile.am:
+#
+# libidn-cyclo.html:
+#      $(PMCCABE) ${top_srcdir}/lib/*.[ch] \
+#              | sort -nr \
+#              | $(AWK) -f ${top_srcdir}/build-aux/pmccabe2html \
+#                      -v lang=html -v name="$(PACKAGE_NAME)" \
+#                      -v 
vcurl="http://git.savannah.gnu.org/gitweb/?p=libidn.git;a=blob;f=%FILENAME%;hb=HEAD";
 \
+#                      -v url="http://www.gnu.org/software/libidn/"; \
+#                      > tmp
+#      mv tmp libidn-cyclo.html
+#
+# The variables available are:
+#   lang     output language, either 'html' or 'wiki'
+#   name     project name
+#   url      link to project's home page
+#   vcurl    URL to version controlled source code browser,
+#            a %FILENAME% in the string is replaced with the relative
+#            source filename
+
+# Prologue & configuration
+BEGIN {
+    section_global_stats_p = 1
+    section_function_cyclo_p = 1
+
+    # "html" or "wiki"
+    package_name = name
+    output_lang = lang
+
+    # General Options
+    cyclo_simple_max = 10
+    cyclo_moderate_max = 20
+    cyclo_high_max = 50
+    cut_dir = "/../"
+    source_file_link_tmpl = vcurl
+
+    # HTML options
+    if (url != "")
+    {
+       html_prolog = "<a href=\"" url "\">Back to " package_name " 
Homepage</a><br/><br/>"
+    }
+    html_epilog = "<hr color=\"black\" size=\"2\"/> \
+Copyright (c) 2007, 2008 Free Software Foundation Inc."
+    css_url = "pmccabe.css"
+    html_doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 
Transitional//EN\" \
+\"http://www.w3.org/TR/html401/loose.dtd\";>"
+    html_comment = "<!-- Generated by gnulib's pmccabe2html at " systime() " 
-->"
+    html_title = "Cyclomatic Complexity report for " package_name
+
+    # Wiki options
+    wiki_prolog = "{{Note|This page has been automatically generated}}"
+    wiki_epilog = ""
+
+    # Internal variables
+    nfuncs = 0;
+}
+
+# Functions
+
+function build_stats()
+{
+    # Maximum modified cyclo
+    for (fcn in mcyclo)
+    {
+        num_of_functions++
+        if (mcyclo[fcn] > max_mcyclo)
+        {
+            max_mcyclo = mcyclo[fcn]
+        }
+
+        if (mcyclo[fcn] > cyclo_high_max)
+        {
+            num_of_untestable_functions++
+        }
+        else if (mcyclo[fcn] > cyclo_moderate_max)
+        {
+            num_of_high_functions++
+        }
+        else if (mcyclo[fcn] > cyclo_simple_max)
+        {
+            num_of_moderate_functions++
+        }
+        else
+        {
+            num_of_simple_functions++
+        }
+    }
+}
+
+function html_fnc_table_complete (caption)
+{
+    html_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
+}
+
+function html_fnc_table_abbrev (caption)
+{
+    html_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
+}
+
+
+function html_fnc_table (caption,
+                         fname_p,
+                         mcyclo_p,
+                         cyclo_p,
+                         num_statements_p,
+                         num_lines_p,
+                         first_line_p,
+                         file_p)
+{
+    print "<table width=\"90%\" class=\"function_table\" cellpadding=\"0\" 
cellspacing=\"0\">"
+    if (caption != "")
+    {
+        print "<caption class=\"function_table_caption\">" caption "</caption>"
+    }
+    html_fnc_header(fname_p, 
+                    mcyclo_p, 
+                    cyclo_p, 
+                    num_statements_p, 
+                    num_lines_p, 
+                    first_line_p, 
+                    file_p)
+    for (nfnc = 1; nfnc < nfuncs; nfnc++)
+    {
+        fnc = fnames[nfnc]
+        html_fnc(fnc, 
+                 fname_p, 
+                 mcyclo_p, 
+                 cyclo_p, 
+                 num_statements_p, 
+                 num_lines_p, 
+                 first_line_p, 
+                 file_p)
+    }
+    print "</table>"
+}
+
+function html_header ()
+{
+    print html_doctype
+    print "<html>"
+    print html_comment
+    print "<head>"
+    print "<title>" html_title "</title>"
+    print ""
+    print "<meta name=\"description\" content=\"" html_title "\">"
+    print "<meta name=\"keywords\" content=\"" html_title "\">"
+    print "<meta name=\"resource-type\" content=\"document\">"
+    print "<meta name=\"distribution\" content=\"global\">"
+    print "<meta name=\"Generator\" content=\"pmccabe2html\">"
+    print "<meta http-equiv=\"Content-Type\" content=\"text/html; 
charset=utf-8\">"
+    print "<script language=\"javascript\" type=\"text/javascript\">"
+    print "function show_hide(idCapa, idButton, fuerzaVisibilidad)\
+{\
+        var button = document.getElementById(idButton);\
+       var capa = document.getElementById(idCapa);\
+       if (capa)\
+       {\
+               if (fuerzaVisibilidad && fuerzaVisibilidad!=\"\") {\
+                       if (fuerzaVisibilidad==\"visible\") 
capa.style.display=\"\";\
+                       else capa.style.display=\"none\";\
+               }\
+               else\
+               {\
+                       if (capa.style.display == \"none\") {\
+                               capa.style.display = \"\";\
+                                button.innerHTML = \"&uarr;\";\
+                       } else {\
+                               capa.style.display = \"none\";\
+                                button.innerHTML = \"&darr;\";     \
+                       }\
+               }\
+       }\
+}"
+    print "</script>"
+
+
+    if (css_url != "")
+    {
+        print "<link rel=\"stylesheet\" href=\"" css_url "\" type 
=\"text/css\" media=\"screen\"/>"
+    }
+    print "</head>"
+    print "<body lang=\"en\" bgcolor=\"#FFFFFF\" text=\"#000000\" 
link=\"#0000FF\" \
+vlink=\"#800080\" alink=\"#FF0000\">"
+}
+
+function html_footer ()
+{
+    print "</body>"
+    print "</html>"
+}
+
+function html_fnc_header (fname_p,
+                          mcyclo_p,
+                          cyclo_p,
+                          num_statements_p,
+                          num_lines_p,
+                          first_line_p,
+                          file_p)
+{
+    print "<tr class=\"function_table_header\">"
+    if (fname_p)
+    {
+        # Function name
+        print "<td class=\"function_table_header_entry\">"
+        print ""
+        print "</td>"
+
+        print "<td class=\"function_table_header_entry\">"
+        print "Function Name"
+        print "</td>"
+    }
+    if (mcyclo_p)
+    {
+        # Modified cyclo
+        print "<td class=\"function_table_header_entry\">"
+        print "Modified Cyclo"
+        print "</td>"
+    }
+    if (cyclo_p)
+    {
+        # Cyclo
+        print "<td class=\"function_table_header_entry\">"
+        print "Cyclomatic"
+        print "<br/>"
+        print "Complexity"
+        print "</td>"
+    }
+    if (num_statements_p)
+    {
+        print "<td class=\"function_table_header_entry\">"
+        print "Number of"
+        print "<br/>"
+        print "Statements"
+        print "</td>"
+    }
+    if (num_lines_p)
+    {
+        print "<td class=\"function_table_header_entry\">"
+        print "Number of"
+        print "<br/>"
+        print "Lines"
+        print "</td>"
+    }
+    if (first_line_p)
+    {
+        print "<td class=\"function_table_header_entry\">"
+        print "First Line"
+        print "</td>"
+    }
+    if (file_p)
+    {
+        print "<td class=\"function_table_header_entry\">"
+        print "Source File"
+        print "</td>"
+
+    }
+    print "</tr>"
+}
+
+function html_fnc (fname,
+                   fname_p,
+                   mcyclo_p,
+                   cyclo_p,
+                   num_statements_p,
+                   num_lines_p,
+                   first_line_p,
+                   file_p)
+{
+    # Function name
+    trclass = "function_entry_simple"
+    if (mcyclo[fname] > cyclo_high_max)
+    {
+        trclass="function_entry_untestable"
+    }   
+    else if (mcyclo[fname] > cyclo_moderate_max)
+    {
+        trclass="function_entry_high"
+    }
+    else if (mcyclo[fname] > cyclo_simple_max)
+    {
+        trclass="function_entry_moderate"
+    }
+
+    print "<tr class=\"" trclass "\">"
+    if (fname_p)
+    {
+        print "<td class=\"function_entry_filename\">"
+        if (mcyclo[fname] > cyclo_simple_max)
+        {
+            print "<a href=\"javascript:void(0);\" title=\"show/hide function 
source\" onClick=\"javascript:show_hide('" fname "_src', '" fname "_button')\">\
+<span id=\"" fname "_button\">&darr;</span></a>"
+        }
+        else
+        {
+            print "&nbsp;"
+        }
+        print "</td>"
+
+        print "<td class=\"function_entry_name\">"
+        print fname
+        print "</td>"
+    }
+    if (mcyclo_p)
+    {
+        # Modified cyclo
+        print "<td class=\"function_entry_cyclo\">"
+        print mcyclo[fname]
+        print "</td>"
+    }
+    if (cyclo_p)
+    {
+        # Cyclo
+        print "<td class=\"function_entry_cyclo\">"
+        print cyclo[fname]
+        print "</td>"
+    }
+    if (num_statements_p)
+    {
+        # Number of statements
+        print "<td class=\"function_entry_number\">"
+        print num_statements[fname]
+        print "</td>"
+    }
+    if (num_lines_p)
+    {
+        # Number of lines
+        print "<td class=\"function_entry_number\">"
+        print num_lines[fname]
+        print "</td>"
+    }
+    if (first_line_p)
+    {
+        # First line
+        print "<td class=\"function_entry_number\">"
+        print first_line[fname]
+        print "</td>"
+    }
+    if (file_p)
+    {
+        href = ""
+        if (source_file_link_tmpl != "")
+        {
+            # Get href target
+            href = source_file_link_tmpl
+            sub(/%FILENAME%/, file[fname], href)
+        }
+
+        # Source file
+        print "<td class=\"function_entry_filename\">"
+        if (href != "")
+        {
+            print "<a href=\"" href "\">" file[fname] "</a>"
+        }
+        else
+        {
+            print file[fname]
+        }
+ 
+        print "</td>"
+
+
+        print "</tr>"
+
+        if (mcyclo[fname] > cyclo_simple_max)
+        {
+            print "<tr>"
+
+            num_columns = 1;
+            if (fname_p) { num_columns++ }
+            if (mcyclo_p) { num_columns++ }
+            if (cyclo_p) { num_columns++ }
+            if (num_statements_p) { num_columns++ }
+            if (num_lines_p) { num_columns++ }
+            if (first_line_p) { num_columns++ }
+            if (file_p) { num_columns++ }
+            
+            print "<td colspan=\"" num_columns "\" height=\"0\">"
+            print "<div id=\"" fname "_src\" class=\"function_src\" 
style=\"position: relative; display: none;\">"
+            print "<pre class=\"function_src\">"
+            while ((getline codeline < (fname "_fn.txt")) > 0)
+            {
+                sub(/\\</, "&lt;", codeline)
+                sub(/\\>/, "&gt;", codeline)
+                sub(/&/, "&amp;", codeline)
+                
+                print codeline
+            }
+            close(fname "_fn.txt")
+            system("rm " fname "_fn.txt")
+            print "</pre>"
+            print "</div>"
+            print "</td>"
+            print "</tr>"
+        }
+
+    }
+}
+
+function html_global_stats ()
+{
+    print "<div class=\"section_title\">Resume</div>"
+
+    print "<br/>"
+    print "<table class=\"resume_table\">"
+    # Total number of functions
+    print "<tr>"
+    print "<td class=\"resume_header_entry\">"
+    print "Total number of functions"
+    print "</td>"
+    print "<td class=\"resume_number_entry\">"
+    print num_of_functions
+    print "</td>"
+    print "</tr>"
+    # Number of simple functions
+    print "<tr>"
+    print "<td class=\"resume_header_entry\">"
+    print "Number of low risk functions"
+    print "</td>"
+    print "<td class=\"resume_number_entry\">"
+    print num_of_simple_functions
+    print "</td>"
+    print "</tr>"
+    # Number of moderate functions
+    print "<tr>"
+    print "<td class=\"resume_header_entry\">"
+    print "Number of moderate risk functions"
+    print "</td>"
+    print "<td class=\"resume_number_entry\">"
+    print num_of_moderate_functions
+    print "</td>"
+    print "</tr>"
+    # Number of high functions
+    print "<tr>"
+    print "<td class=\"resume_header_entry\">"
+    print "Number of high risk functions"
+    print "</td>"
+    print "<td class=\"resume_number_entry\">"
+    print num_of_high_functions
+    print "</td>"
+    print "</tr>"
+    # Number of untestable functions
+    print "<tr>"
+    print "<td class=\"resume_header_entry\">"
+    print "Number of untestable functions"
+    print "</td>"
+    print "<td class=\"resume_number_entry\">"
+    print num_of_untestable_functions
+    print "</td>"
+    print "</tr>"
+    print "</table>"
+    print "<br/>"
+}
+
+function html_function_cyclo ()
+{
+    print "<div class=\"section_title\">Details for all functions</div>"
+    print "<p>Used ranges:</p>"
+
+    print "<table class=\"ranges_table\">"
+    print "<tr>"
+    print "<td class=\"ranges_header_entry\">"
+    print "&nbsp;"
+    print "</td>"
+    print "<td class=\"ranges_header_entry\">"
+    print "Cyclomatic Complexity"
+    print "</td>"
+    print "<td class=\"ranges_header_entry\">"
+    print "Risk Evaluation"
+    print "</td>"
+    print "</tr>"
+    # Simple
+    print "<tr>"
+    print "<td class=\"ranges_entry_simple\">"
+    print "&nbsp;"
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print "0 - " cyclo_simple_max
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print "Simple module, without much risk"
+    print "</td>"
+    print "</tr>"
+    # Moderate 
+    print "<tr>"
+    print "<td class=\"ranges_entry_moderate\">"
+    print "&nbsp;"
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print cyclo_simple_max + 1 " - " cyclo_moderate_max
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print "More complex module, moderate risk"
+    print "</td>"
+    print "</tr>"
+    # High
+    print "<tr>"
+    print "<td class=\"ranges_entry_high\">"
+    print "&nbsp;"
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print cyclo_moderate_max + 1 " - " cyclo_high_max
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print "Complex module, high risk"
+    print "</td>"
+    print "</tr>"
+    # Untestable
+    print "<tr>"
+    print "<td class=\"ranges_entry_untestable\">"
+    print "&nbsp;"
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print "greater than " cyclo_high_max
+    print "</td>"
+    print "<td class=\"ranges_entry\">"
+    print "Untestable module, very high risk"
+    print "</td>"
+    print "</tr>"
+    print "</table>"
+    print "<br/>"
+    html_fnc_table_complete("")
+}
+
+function wiki_global_stats ()
+{
+    print "{| class=\"cyclo_resume_table\""
+    # Total number of functions
+    print "|-"
+    print "| class=\"cyclo_resume_header_entry\" | Total number of functions"
+    print "| class=\"cyclo_resume_number_entry\" |" num_of_functions
+    # Number of simple functions
+    print "|-"
+    print "| class=\"cyclo_resume_header_entry\" | Number of low risk 
functions"
+    print "| class=\"cyclo_resume_number_entry\" |" num_of_simple_functions
+    # Number of moderate functions
+    print "|-"
+    print "| class=\"cyclo_resume_header_entry\" | Number of moderate risk 
functions"
+    print "| class=\"cyclo_resume_number_entry\" |" num_of_moderate_functions
+    # Number of high functions
+    print "|-"
+    print "| class=\"cyclo_resume_header_entry\" | Number of high risk 
functions"
+    print "| class=\"cyclo_resume_number_entry\" |" num_of_high_functions
+    # Number of untestable functions
+    print "|-"
+    print "| class=\"cyclo_resume_header_entry\" | Number of untestable 
functions"
+    print "| class=\"cyclo_resume_number_entry\" |" num_of_untestable_functions
+    print "|}"
+}
+
+function wiki_function_cyclo ()
+{
+    print "==Details for all functions=="
+
+    print "Used ranges:"
+    
+    print "{| class =\"cyclo_ranges_table\""
+    print "|-"
+    print "| class=\"cyclo_ranges_header_entry\" | "
+    print "| class=\"cyclo_ranges_header_entry\" | Cyclomatic Complexity"
+    print "| class=\"cyclo_ranges_header_entry\" | Risk Evaluation"
+    # Simple
+    print "|-"
+    print "| class=\"cyclo_ranges_entry_simple\" | "
+    print "| class=\"cyclo_ranges_entry\" | 0 - " cyclo_simple_max
+    print "| class=\"cyclo_ranges_entry\" | Simple module, without much risk"
+    # Moderate
+    print "|-"
+    print "| class=\"cyclo_ranges_entry_moderate\" | "
+    print "| class=\"cyclo_ranges_entry\" |" cyclo_simple_max + 1 " - " 
cyclo_moderate_max
+    print "| class=\"cyclo_ranges_entry\" | More complex module, moderate risk"
+    # High
+    print "|-"
+    print "| class=\"cyclo_ranges_entry_high\" | "
+    print "| class=\"cyclo_ranges_entry\" |" cyclo_moderate_max + 1 " - " 
cyclo_high_max
+    print "| class=\"cyclo_ranges_entry\" | Complex module, high risk"
+    # Untestable
+    print "|-"
+    print "| class=\"cyclo_ranges_entry_untestable\" | "
+    print "| class=\"cyclo_ranges_entry\" | greater than " cyclo_high_max
+    print "| class=\"cyclo_ranges_entry\" | Untestable module, very high risk"
+    print "|}"
+
+    print ""
+    print ""
+    wiki_fnc_table_complete("")
+}
+
+function wiki_fnc_table_complete (caption)
+{
+    wiki_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
+}
+
+function wiki_fnc_table_abbrev (caption)
+{
+    wiki_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
+}
+
+function wiki_fnc_table (caption,
+                         fname_p,
+                         mcyclo_p,
+                         cyclo_p,
+                         num_statements_p,
+                         num_lines_p,
+                         first_line_p,
+                         file_p)
+{
+    print "{| width=\"90%\" class=\"cyclo_function_table\" cellpadding=\"0\" 
cellspacing=\"0\">"
+    if (caption != "")
+    {
+        print "|+" caption
+    }
+    wiki_fnc_header(fname_p, 
+                    mcyclo_p, 
+                    cyclo_p, 
+                    num_statements_p, 
+                    num_lines_p, 
+                    first_line_p, 
+                    file_p)
+    for (nfnc = 1; nfnc < nfuncs; nfnc++)
+    {
+        fnc = fnames[nfnc]
+        wiki_fnc(fnc, 
+                 fname_p, 
+                 mcyclo_p, 
+                 cyclo_p, 
+                 num_statements_p, 
+                 num_lines_p, 
+                 first_line_p, 
+                 file_p)
+    }
+    print "|}"
+}
+
+function wiki_fnc_header (fname_p,
+                          mcyclo_p,
+                          cyclo_p,
+                          num_statements_p,
+                          num_lines_p,
+                          first_line_p,
+                          file_p)
+{
+    if (fname_p)
+    {
+        # Function name
+        print "! class=\"cyclo_function_table_header_entry\" | Function Name"
+    }
+    if (mcyclo_p)
+    {
+        # Modified cyclo
+        print "! class=\"cyclo_function_table_header_entry\" | Modified Cyclo"
+    }
+    if (cyclo_p)
+    {
+        # Cyclo
+        print "! class=\"cyclo_function_table_header_entry\" | Cyclomatic 
Complexity"
+    }
+    if (num_statements_p)
+    {
+        print "! class=\"cyclo_function_table_header_entry\" | Number of 
Statements"
+    }
+    if (num_lines_p)
+    {
+        print "! class=\"cyclo_function_table_header_entry\" | Number of Lines"
+    }
+    if (first_line_p)
+    {
+        print "! class=\"cyclo_function_table_header_entry\" | First Line"
+    }
+    if (file_p)
+    {
+        print "! class=\"cyclo_function_table_header_entry\" | Source File"
+    }
+}
+
+function wiki_fnc (fname,
+                   fname_p,
+                   mcyclo_p,
+                   cyclo_p,
+                   num_statements_p,
+                   num_lines_p,
+                   first_line_p,
+                   file_p)
+{
+    # Function name
+    trclass = "cyclo_function_entry_simple"
+    if (mcyclo[fname] > cyclo_high_max)
+    {
+        trclass="cyclo_function_entry_untestable"
+    }   
+    else if (mcyclo[fname] > cyclo_moderate_max)
+    {
+        trclass="cyclo_function_entry_high"
+    }
+    else if (mcyclo[fname] > cyclo_simple_max)
+    {
+        trclass="cyclo_function_entry_moderate"
+    }
+
+    print "|- class=\"" trclass "\""
+    if (fname_p)
+    {
+        print "| class=\"cyclo_function_entry_name\" |" fname
+    }
+    if (mcyclo_p)
+    {
+        # Modified cyclo
+        print "| class=\"cyclo_function_entry_cyclo\" |" mcyclo[fname]
+    }
+    if (cyclo_p)
+    {
+        # Cyclo
+        print "| class=\"cyclo_function_entry_cyclo\" |" cyclo[fname]
+    }
+    if (num_statements_p)
+    {
+        # Number of statements
+        print "| class=\"cyclo_function_entry_number\" |" num_statements[fname]
+    }
+    if (num_lines_p)
+    {
+        # Number of lines
+        print "| class=\"cyclo_function_entry_number\" |" num_lines[fname]
+    }
+    if (first_line_p)
+    {
+        # First line
+        print "| class=\"cyclo_function_entry_number\" |" first_line[fname]
+    }
+    if (file_p)
+    {
+        href = ""
+        if (source_file_link_tmpl != "")
+        {
+            # Get href target
+            href = source_file_link_tmpl
+            sub(/%FILENAME%/, file[fname], href)
+        }
+        
+        # Source file
+        print "| class=\"cyclo_function_entry_filename\" |" \
+            ((href != "") ? "[" href " " file[fname] "]" : "[" file[fname] "]")
+    }
+}
+
+# Scan data from a line
+{
+    function_name = $7
+
+    nfuncs++;
+    fnames[nfuncs] = function_name
+    mcyclo[function_name] = $1
+    cyclo[function_name] = $2
+    num_statements[function_name] = $3
+    first_line[function_name] = $4
+    num_lines[function_name] = $5
+
+    # Build the filename from the file_spec ($6)
+    begin_util_path = index($6, cut_dir)
+    tmpfilename = substr($6, begin_util_path + length(cut_dir))
+    sub(/\([0-9]+\):/, "", tmpfilename)
+    file[function_name] = tmpfilename
+
+    if (mcyclo[function_name] > cyclo_simple_max)
+    {
+        # Extract function contents to a fn_txt file
+        filepath = $6
+        sub(/\([0-9]+\):/, "", filepath)
+        num_line = 0
+        while ((getline codeline < filepath) > 0)
+        {
+            num_line++;
+            if ((num_line >= first_line[function_name]) &&
+                (num_line < first_line[function_name] + 
num_lines[function_name]))
+            {
+                print codeline > (function_name "_fn.txt")
+            }
+        }
+        close (function_name "_fn.txt")
+        close(filepath)
+    }
+
+    # Initial values for statistics variables
+    num_of_functions = 0
+    max_mcyclo = 0
+    max_function_length = 0
+    num_of_simple_functions = 0
+    num_of_moderate_functions = 0
+    num_of_high_functions = 0
+    num_of_untestable_functions = 0
+}
+
+# Epilogue
+END {
+    # Print header (only for html)
+    if (output_lang == "html")
+    {
+        html_header()
+    }
+
+    # Print prolog
+    if ((output_lang == "html") && 
+        (html_prolog != ""))
+    {
+        print html_prolog
+    }
+    if ((output_lang == "wiki") &&
+        (wiki_prolog != ""))
+    {
+        print wiki_prolog
+    }
+
+    if (output_lang == "html")
+    {
+        print "<div class=\"page_title\">" package_name " Cyclomatic 
Complexity Report</div>"
+        print "<p>Report generated at: <span class=\"report_timestamp\">" 
strftime() "</div></p>"
+    }
+    if (output_lang == "wiki")
+    {
+        print "==" package_name " Cyclomatic Complexity Report=="
+        print "Report generated at: '''" strftime() "'''"
+    }
+
+    if (section_global_stats_p)
+    {
+        build_stats()
+
+        if (output_lang == "html")
+        {
+            html_global_stats()
+        }
+        if (output_lang == "wiki")
+        {
+            wiki_global_stats()
+        }
+    }
+    if (section_function_cyclo_p)
+    {
+        if (output_lang == "html")
+        {
+            html_function_cyclo()
+        }
+        if (output_lang == "wiki")
+        {
+            wiki_function_cyclo()
+        }
+    }
+    
+    # Print epilog
+    if ((output_lang == "html") && 
+        (html_epilog != ""))
+    {
+        print html_epilog
+    }
+    if ((output_lang == "wiki") &&
+        (wiki_epilog != ""))
+    {
+        print wiki_epilog
+    }
+
+    # Print footer (html only)
+    if (output_lang == "html")
+    {
+        html_footer()
+    }
+}
+
+# End of pmccabe2html
diff --git a/m4/pmccabe2html.m4 b/m4/pmccabe2html.m4
new file mode 100644
index 0000000..5e20742
--- /dev/null
+++ b/m4/pmccabe2html.m4
@@ -0,0 +1,14 @@
+# pmccabe2html.m4 serial 1
+dnl Copyright (C) 2008 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Simon Josefsson
+
+# Usage: gl_PMCCABE2HTML([]).
+AC_DEFUN([gl_PMCCABE2HTML],
+[
+  AC_PROG_AWK
+  AC_PATH_PROG([PMCCABE], [pmccabe], [false])
+])
diff --git a/modules/pmccabe2html b/modules/pmccabe2html
new file mode 100644
index 0000000..50db333
--- /dev/null
+++ b/modules/pmccabe2html
@@ -0,0 +1,23 @@
+Description:
+Produce fancy cyclomatic code complexity charts, using pmccabe.
+See <http://www.parisc-linux.org/~bame/pmccabe/>.
+
+Files:
+m4/pmccabe2html.m4
+build-aux/pmccabe2html
+build-aux/pmccabe.css
+
+Depends-on:
+
+configure.ac:
+gl_PMCCABE2HTML
+
+Makefile.am:
+
+Include:
+
+License:
+GPLed build tool
+
+Maintainer:
+gnupdf
-- 
1.5.6.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]