.
# Typical Invocation is from a Makefile.am:
#
# CYCLO_SOURCES = ${top_srcdir}/src/*.[ch]
#
# cyclo-$(PACKAGE).html: $(CYCLO_SOURCES)
# 	$(PMCCABE) $(CYCLO_SOURCES) \
# 		| 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 \
# 			-v cut_dir=${top_srcdir}/ \
# 			> $@-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
    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, 1, 0, 1, 1, 0, 1)
}
function html_fnc_table_abbrev (caption)
{
    html_fnc_table(caption, 1, 1, 0, 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 "Summary
"
    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 ""
    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_summary_table\""
    # Total number of functions
    print "|-"
    print "| class=\"cyclo_summary_header_entry\" | Total number of functions"
    print "| class=\"cyclo_summary_number_entry\" |" num_of_functions
    # Number of simple functions
    print "|-"
    print "| class=\"cyclo_summary_header_entry\" | Number of low risk functions"
    print "| class=\"cyclo_summary_number_entry\" |" num_of_simple_functions
    # Number of moderate functions
    print "|-"
    print "| class=\"cyclo_summary_header_entry\" | Number of moderate risk functions"
    print "| class=\"cyclo_summary_number_entry\" |" num_of_moderate_functions
    # Number of high functions
    print "|-"
    print "| class=\"cyclo_summary_header_entry\" | Number of high risk functions"
    print "| class=\"cyclo_summary_number_entry\" |" num_of_high_functions
    # Number of untestable functions
    print "|-"
    print "| class=\"cyclo_summary_header_entry\" | Number of untestable functions"
    print "| class=\"cyclo_summary_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, 1, 0, 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