.
# Typical Invocation is from a Makefile.am:
#
# cyclo-$(PACKAGE).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=$(PACKAGE).git;a=blob;f=%FILENAME%;hb=HEAD" \
# -v url="http://www.gnu.org/software/$(PACKAGE)/" \
# -v css=${top_srcdir}/build-aux/pmccabe.css \
# > $@-tmp
# mv $@-tmp $@
#
# 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
# css CSS stylesheet filename, included verbatim in HTML output
# css_url link to CSS stylesheet, an URL
# 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 = "Back to " package_name " Homepage "
}
html_epilog = " \
Copyright (c) 2007, 2008 Free Software Foundation, Inc."
html_doctype = ""
html_comment = ""
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, 1, 0, 1, 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 ""
if (caption != "")
{
print "" 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++)
{
html_fnc(nfnc,
fname_p,
mcyclo_p,
cyclo_p,
num_statements_p,
num_lines_p,
first_line_p,
file_p)
}
print "
"
}
function html_header ()
{
print html_doctype
print ""
print html_comment
print ""
print "" html_title " "
print ""
print " "
print " "
print " "
print " "
print " "
print " "
print ""
if (css_url != "")
{
print " "
}
if (css != "")
{
print ""
close(css)
}
print ""
print ""
}
function html_footer ()
{
print ""
print ""
}
function html_fnc_header (fname_p,
mcyclo_p,
cyclo_p,
num_statements_p,
num_lines_p,
first_line_p,
file_p)
{
print ""
}
function html_fnc (nfun,
fname_p,
mcyclo_p,
cyclo_p,
num_statements_p,
num_lines_p,
first_line_p,
file_p)
{
fname = fnames[nfun]
# Function name
trclass = "function_entry_simple"
if (mcyclo[nfun] > cyclo_high_max)
{
trclass="function_entry_untestable"
}
else if (mcyclo[nfun] > cyclo_moderate_max)
{
trclass="function_entry_high"
}
else if (mcyclo[nfun] > cyclo_simple_max)
{
trclass="function_entry_moderate"
}
print ""
if (fname_p)
{
print ""
if (file_p && mcyclo[nfun] > cyclo_simple_max)
{
print "\
↓ "
}
else
{
print " "
}
print " "
print ""
print fname
print " "
}
if (mcyclo_p)
{
# Modified cyclo
print ""
print mcyclo[nfun]
print " "
}
if (cyclo_p)
{
# Cyclo
print ""
print cyclo[nfun]
print " "
}
if (num_statements_p)
{
# Number of statements
print ""
print num_statements[nfun]
print " "
}
if (num_lines_p)
{
# Number of lines
print ""
print num_lines[nfun]
print " "
}
if (first_line_p)
{
# First line
print ""
print first_line[nfun]
print " "
}
if (file_p)
{
href = ""
if (source_file_link_tmpl != "")
{
# Get href target
href = source_file_link_tmpl
sub(/%FILENAME%/, file[nfun], href)
}
# Source file
print ""
if (href != "")
{
print "" file[nfun] " "
}
else
{
print file[nfun]
}
print " "
print " "
if (mcyclo[nfun] > cyclo_simple_max)
{
print ""
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 ""
print ""
print "
"
while ((getline codeline < (fname nfun "_fn.txt")) > 0)
{
sub(/\\, "<", codeline)
sub(/\\>/, ">", codeline)
sub(/&/, "&", codeline)
print codeline
}
close(fname nfun "_fn.txt")
system("rm " fname nfun "_fn.txt")
print " "
print "
"
print " "
print " "
}
}
}
function html_global_stats ()
{
print "Resume
"
print " "
print ""
# Total number of functions
print ""
print ""
print ""
print num_of_functions
print " "
print " "
# Number of simple functions
print ""
print ""
print ""
print num_of_simple_functions
print " "
print " "
# Number of moderate functions
print ""
print ""
print ""
print num_of_moderate_functions
print " "
print " "
# Number of high functions
print ""
print ""
print ""
print num_of_high_functions
print " "
print " "
# Number of untestable functions
print ""
print ""
print ""
print num_of_untestable_functions
print " "
print " "
print "
"
print " "
}
function html_function_cyclo ()
{
print "Details for all functions
"
print "Used ranges:
"
print ""
print ""
print ""
print ""
print ""
print " "
# Simple
print ""
print ""
print " "
print " "
print ""
print "0 - " cyclo_simple_max
print " "
print ""
print "Simple module, without much risk"
print " "
print " "
# Moderate
print ""
print ""
print " "
print " "
print ""
print cyclo_simple_max + 1 " - " cyclo_moderate_max
print " "
print ""
print "More complex module, moderate risk"
print " "
print " "
# High
print ""
print ""
print " "
print " "
print ""
print cyclo_moderate_max + 1 " - " cyclo_high_max
print " "
print ""
print "Complex module, high risk"
print " "
print " "
# Untestable
print ""
print ""
print " "
print " "
print ""
print "greater than " cyclo_high_max
print " "
print ""
print "Untestable module, very high risk"
print " "
print " "
print "
"
print " "
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++)
{
wiki_fnc(nfnc,
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 (nfnc,
fname_p,
mcyclo_p,
cyclo_p,
num_statements_p,
num_lines_p,
first_line_p,
file_p)
{
fname = fnames[nfnc]
# Function name
trclass = "cyclo_function_entry_simple"
if (mcyclo[nfnc] > cyclo_high_max)
{
trclass="cyclo_function_entry_untestable"
}
else if (mcyclo[nfnc] > cyclo_moderate_max)
{
trclass="cyclo_function_entry_high"
}
else if (mcyclo[nfnc] > 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[nfnc]
}
if (cyclo_p)
{
# Cyclo
print "| class=\"cyclo_function_entry_cyclo\" |" cyclo[nfnc]
}
if (num_statements_p)
{
# Number of statements
print "| class=\"cyclo_function_entry_number\" |" num_statements[nfnc]
}
if (num_lines_p)
{
# Number of lines
print "| class=\"cyclo_function_entry_number\" |" num_lines[nfnc]
}
if (first_line_p)
{
# First line
print "| class=\"cyclo_function_entry_number\" |" first_line[nfnc]
}
if (file_p)
{
href = ""
if (source_file_link_tmpl != "")
{
# Get href target
href = source_file_link_tmpl
sub(/%FILENAME%/, file[nfnc], href)
}
# Source file
print "| class=\"cyclo_function_entry_filename\" |" \
((href != "") ? "[" href " " file[nfnc] "]" : "[" file[nfnc] "]")
}
}
# Scan data from a line
{
function_name = $7
nfuncs++;
fnames[nfuncs] = function_name
mcyclo[nfuncs] = $1
cyclo[nfuncs] = $2
num_statements[nfuncs] = $3
first_line[nfuncs] = $4
num_lines[nfuncs] = $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[nfuncs] = tmpfilename
if (mcyclo[nfuncs] > 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[nfuncs]) &&
(num_line < first_line[nfuncs] + num_lines[nfuncs]))
{
print codeline > (function_name nfuncs "_fn.txt")
}
}
close (function_name nfuncs "_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 "" package_name " Cyclomatic Complexity Report
"
print "Report generated at: " strftime() "
"
}
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