Blob Blame History Raw
# pmccabe2html - AWK script to convert pmccabe output to html       -*- awk -*-

# Copyright (C) 2007-2020 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 <https://www.gnu.org/licenses/>.

# Written by Jose E. Marchesi <jemarch@gnu.org>.
# Adapted for gnulib by Simon Josefsson <simon@josefsson.org>.
# Added support for C++ by Giuseppe Scrivano <gscrivano@gnu.org>.

# 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="https://git.savannah.gnu.org/gitweb/?p=$(PACKAGE).git;a=blob;f=%FILENAME%;hb=HEAD" \
# 			-v url="https://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 {
    # Portable lookup of present time.
    "date +%s" | getline epoch_time
    "date" | getline chronos_time

    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 = "<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."
    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 " epoch_time " -->"
    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 "<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++)
    {
        html_fnc(nfnc,
                 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\"/>"
    }
    if (css != "")
    {
        print "<style type =\"text/css\" media=\"screen\">"
	print "<!--"
        while ((getline cssline < css) > 0)
        {
	    print cssline
	}
        print "-->"
	print "</style>"
	close(css)
    }
    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 (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 "<tr class=\"" trclass "\">"
    if (fname_p)
    {
        print "<td class=\"function_entry_filename\">"
        if (file_p && mcyclo[nfun] > 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[nfun]
        print "</td>"
    }
    if (cyclo_p)
    {
        # Cyclo
        print "<td class=\"function_entry_cyclo\">"
        print cyclo[nfun]
        print "</td>"
    }
    if (num_statements_p)
    {
        # Number of statements
        print "<td class=\"function_entry_number\">"
        print num_statements[nfun]
        print "</td>"
    }
    if (num_lines_p)
    {
        # Number of lines
        print "<td class=\"function_entry_number\">"
        print num_lines[nfun]
        print "</td>"
    }
    if (first_line_p)
    {
        # First line
        print "<td class=\"function_entry_number\">"
        print first_line[nfun]
        print "</td>"
    }
    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 "<td class=\"function_entry_filename\">"
        if (href != "")
        {
            print "<a href=\"" href "\">" file[nfun] "</a>"
        }
        else
        {
            print file[nfun]
        }

        print "</td>"


        print "</tr>"

        if (mcyclo[nfun] > 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 nfun "_fn.txt")) > 0)
            {
                gsub(/&/, "\\&amp;", codeline)	# Must come first.
                gsub(/</, "\\&lt;", codeline)
                gsub(/>/, "\\&gt;", codeline)

                print codeline
            }
            close(fname nfun "_fn.txt")
            system("rm " "'" fname "'" nfun "_fn.txt")
            print "</pre>"
            print "</div>"
            print "</td>"
            print "</tr>"
        }

    }
}

function html_global_stats ()
{
    print "<div class=\"section_title\">Summary</div>"

    print "<table class=\"summary_table\">"
    # Total number of functions
    print "<tr>"
    print "<td class=\"summary_header_entry\">"
    print "Total number of functions"
    print "</td>"
    print "<td class=\"summary_number_entry\">"
    print num_of_functions
    print "</td>"
    print "</tr>"
    # Number of simple functions
    print "<tr>"
    print "<td class=\"summary_header_entry\">"
    print "Number of low risk functions"
    print "</td>"
    print "<td class=\"summary_number_entry\">"
    print num_of_simple_functions
    print "</td>"
    print "</tr>"
    # Number of moderate functions
    print "<tr>"
    print "<td class=\"summary_header_entry\">"
    print "Number of moderate risk functions"
    print "</td>"
    print "<td class=\"summary_number_entry\">"
    print num_of_moderate_functions
    print "</td>"
    print "</tr>"
    # Number of high functions
    print "<tr>"
    print "<td class=\"summary_header_entry\">"
    print "Number of high risk functions"
    print "</td>"
    print "<td class=\"summary_number_entry\">"
    print num_of_high_functions
    print "</td>"
    print "</tr>"
    # Number of untestable functions
    print "<tr>"
    print "<td class=\"summary_header_entry\">"
    print "Number of untestable functions"
    print "</td>"
    print "<td class=\"summary_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 "<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_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 "<div class=\"page_title\">" package_name " Cyclomatic Complexity Report</div>"
        print "<p>Report generated at: <span class=\"report_timestamp\">" chronos_time "</span></p>"
    }
    if (output_lang == "wiki")
    {
        print "==" package_name " Cyclomatic Complexity Report=="
        print "Report generated at: '''" chronos_time "'''"
    }

    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