1 # pmccabe2html - AWK script to convert pmccabe output to html -*- awk -*-
3 # Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # Written by Jose E. Marchesi <jemarch@gnu.org>.
19 # Adapted for gnulib by Simon Josefsson <simon@josefsson.org>.
20 # Added support for C++ by Giuseppe Scrivano <gscrivano@gnu.org>.
22 # Typical Invocation is from a Makefile.am:
24 # cyclo-$(PACKAGE).html:
25 # $(PMCCABE) ${top_srcdir}/lib/*.[ch] \
27 # | $(AWK) -f ${top_srcdir}/build-aux/pmccabe2html \
28 # -v lang=html -v name="$(PACKAGE_NAME)" \
29 # -v vcurl="http://git.savannah.gnu.org/gitweb/?p=$(PACKAG).git;a=blob;f=%FILENAME%;hb=HEAD" \
30 # -v url="http://www.gnu.org/software/$(PACKAGE)/" \
31 # -v css=${top_srcdir}/build-aux/pmccabe.css \
32 # -v cut_dir=${top_srcdir}/ \
36 # The variables available are:
37 # lang output language, either 'html' or 'wiki'
39 # url link to project's home page
40 # vcurl URL to version controlled source code browser,
41 # a %FILENAME% in the string is replaced with the relative
43 # css CSS stylesheet filename, included verbatim in HTML output
44 # css_url link to CSS stylesheet, an URL
46 # Prologue & configuration
48 section_global_stats_p = 1
49 section_function_cyclo_p = 1
57 cyclo_moderate_max = 20
59 source_file_link_tmpl = vcurl
64 html_prolog = "<a href=\"" url "\">Back to " package_name " Homepage</a><br/><br/>"
66 html_epilog = "<hr color=\"black\" size=\"2\"/> \
67 Copyright (c) 2007, 2008 Free Software Foundation, Inc."
68 html_doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \
69 \"http://www.w3.org/TR/html401/loose.dtd\">"
70 html_comment = "<!-- Generated by gnulib's pmccabe2html at " systime() " -->"
71 html_title = "Cyclomatic Complexity report for " package_name
74 wiki_prolog = "{{Note|This page has been automatically generated}}"
83 function build_stats()
85 # Maximum modified cyclo
89 if (mcyclo[fcn] > max_mcyclo)
91 max_mcyclo = mcyclo[fcn]
94 if (mcyclo[fcn] > cyclo_high_max)
96 num_of_untestable_functions++
98 else if (mcyclo[fcn] > cyclo_moderate_max)
100 num_of_high_functions++
102 else if (mcyclo[fcn] > cyclo_simple_max)
104 num_of_moderate_functions++
108 num_of_simple_functions++
113 function html_fnc_table_complete (caption)
115 html_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
118 function html_fnc_table_abbrev (caption)
120 html_fnc_table(caption, 1, 0, 1, 0, 1, 0, 0)
124 function html_fnc_table (caption,
133 print "<table width=\"90%\" class=\"function_table\" cellpadding=\"0\" cellspacing=\"0\">"
136 print "<caption class=\"function_table_caption\">" caption "</caption>"
138 html_fnc_header(fname_p,
145 for (nfnc = 1; nfnc < nfuncs; nfnc++)
159 function html_header ()
165 print "<title>" html_title "</title>"
167 print "<meta name=\"description\" content=\"" html_title "\">"
168 print "<meta name=\"keywords\" content=\"" html_title "\">"
169 print "<meta name=\"resource-type\" content=\"document\">"
170 print "<meta name=\"distribution\" content=\"global\">"
171 print "<meta name=\"Generator\" content=\"pmccabe2html\">"
172 print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
173 print "<script language=\"javascript\" type=\"text/javascript\">"
174 print "function show_hide(idCapa, idButton, fuerzaVisibilidad)\
176 var button = document.getElementById(idButton);\
177 var capa = document.getElementById(idCapa);\
180 if (fuerzaVisibilidad && fuerzaVisibilidad!=\"\") {\
181 if (fuerzaVisibilidad==\"visible\") capa.style.display=\"\";\
182 else capa.style.display=\"none\";\
186 if (capa.style.display == \"none\") {\
187 capa.style.display = \"\";\
188 button.innerHTML = \"↑\";\
190 capa.style.display = \"none\";\
191 button.innerHTML = \"↓\"; \
201 print "<link rel=\"stylesheet\" href=\"" css_url "\" type =\"text/css\" media=\"screen\"/>"
205 print "<style type =\"text/css\" media=\"screen\">"
207 while ((getline cssline < css) > 0)
216 print "<body lang=\"en\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" \
217 vlink=\"#800080\" alink=\"#FF0000\">"
220 function html_footer ()
226 function html_fnc_header (fname_p,
234 print "<tr class=\"function_table_header\">"
238 print "<td class=\"function_table_header_entry\">"
242 print "<td class=\"function_table_header_entry\">"
243 print "Function Name"
249 print "<td class=\"function_table_header_entry\">"
250 print "Modified Cyclo"
256 print "<td class=\"function_table_header_entry\">"
262 if (num_statements_p)
264 print "<td class=\"function_table_header_entry\">"
272 print "<td class=\"function_table_header_entry\">"
280 print "<td class=\"function_table_header_entry\">"
286 print "<td class=\"function_table_header_entry\">"
294 function html_fnc (nfun,
306 trclass = "function_entry_simple"
307 if (mcyclo[nfun] > cyclo_high_max)
309 trclass="function_entry_untestable"
311 else if (mcyclo[nfun] > cyclo_moderate_max)
313 trclass="function_entry_high"
315 else if (mcyclo[nfun] > cyclo_simple_max)
317 trclass="function_entry_moderate"
320 print "<tr class=\"" trclass "\">"
323 print "<td class=\"function_entry_filename\">"
324 if (file_p && mcyclo[nfun] > cyclo_simple_max)
326 print "<a href=\"javascript:void(0);\" title=\"show/hide function source\" onClick=\"javascript:show_hide('" fname "_src', '" fname "_button')\">\
327 <span id=\"" fname "_button\">↓</span></a>"
335 print "<td class=\"function_entry_name\">"
342 print "<td class=\"function_entry_cyclo\">"
349 print "<td class=\"function_entry_cyclo\">"
353 if (num_statements_p)
355 # Number of statements
356 print "<td class=\"function_entry_number\">"
357 print num_statements[nfun]
363 print "<td class=\"function_entry_number\">"
364 print num_lines[nfun]
370 print "<td class=\"function_entry_number\">"
371 print first_line[nfun]
377 if (source_file_link_tmpl != "")
380 href = source_file_link_tmpl
381 sub(/%FILENAME%/, file[nfun], href)
385 print "<td class=\"function_entry_filename\">"
388 print "<a href=\"" href "\">" file[nfun] "</a>"
400 if (mcyclo[nfun] > cyclo_simple_max)
405 if (fname_p) { num_columns++ }
406 if (mcyclo_p) { num_columns++ }
407 if (cyclo_p) { num_columns++ }
408 if (num_statements_p) { num_columns++ }
409 if (num_lines_p) { num_columns++ }
410 if (first_line_p) { num_columns++ }
411 if (file_p) { num_columns++ }
413 print "<td colspan=\"" num_columns "\" height=\"0\">"
414 print "<div id=\"" fname "_src\" class=\"function_src\" style=\"position: relative; display: none;\">"
415 print "<pre class=\"function_src\">"
417 while ((getline codeline < (fname nfun "_fn.txt")) > 0)
419 sub(/\\</, "<", codeline)
420 sub(/\\>/, ">", codeline)
421 sub(/&/, "&", codeline)
425 close(fname nfun "_fn.txt")
426 system("rm " fname nfun "_fn.txt")
436 function html_global_stats ()
438 print "<div class=\"section_title\">Resume</div>"
441 print "<table class=\"resume_table\">"
442 # Total number of functions
444 print "<td class=\"resume_header_entry\">"
445 print "Total number of functions"
447 print "<td class=\"resume_number_entry\">"
448 print num_of_functions
451 # Number of simple functions
453 print "<td class=\"resume_header_entry\">"
454 print "Number of low risk functions"
456 print "<td class=\"resume_number_entry\">"
457 print num_of_simple_functions
460 # Number of moderate functions
462 print "<td class=\"resume_header_entry\">"
463 print "Number of moderate risk functions"
465 print "<td class=\"resume_number_entry\">"
466 print num_of_moderate_functions
469 # Number of high functions
471 print "<td class=\"resume_header_entry\">"
472 print "Number of high risk functions"
474 print "<td class=\"resume_number_entry\">"
475 print num_of_high_functions
478 # Number of untestable functions
480 print "<td class=\"resume_header_entry\">"
481 print "Number of untestable functions"
483 print "<td class=\"resume_number_entry\">"
484 print num_of_untestable_functions
491 function html_function_cyclo ()
493 print "<div class=\"section_title\">Details for all functions</div>"
494 print "<p>Used ranges:</p>"
496 print "<table class=\"ranges_table\">"
498 print "<td class=\"ranges_header_entry\">"
501 print "<td class=\"ranges_header_entry\">"
502 print "Cyclomatic Complexity"
504 print "<td class=\"ranges_header_entry\">"
505 print "Risk Evaluation"
510 print "<td class=\"ranges_entry_simple\">"
513 print "<td class=\"ranges_entry\">"
514 print "0 - " cyclo_simple_max
516 print "<td class=\"ranges_entry\">"
517 print "Simple module, without much risk"
522 print "<td class=\"ranges_entry_moderate\">"
525 print "<td class=\"ranges_entry\">"
526 print cyclo_simple_max + 1 " - " cyclo_moderate_max
528 print "<td class=\"ranges_entry\">"
529 print "More complex module, moderate risk"
534 print "<td class=\"ranges_entry_high\">"
537 print "<td class=\"ranges_entry\">"
538 print cyclo_moderate_max + 1 " - " cyclo_high_max
540 print "<td class=\"ranges_entry\">"
541 print "Complex module, high risk"
546 print "<td class=\"ranges_entry_untestable\">"
549 print "<td class=\"ranges_entry\">"
550 print "greater than " cyclo_high_max
552 print "<td class=\"ranges_entry\">"
553 print "Untestable module, very high risk"
558 html_fnc_table_complete("")
561 function wiki_global_stats ()
563 print "{| class=\"cyclo_resume_table\""
564 # Total number of functions
566 print "| class=\"cyclo_resume_header_entry\" | Total number of functions"
567 print "| class=\"cyclo_resume_number_entry\" |" num_of_functions
568 # Number of simple functions
570 print "| class=\"cyclo_resume_header_entry\" | Number of low risk functions"
571 print "| class=\"cyclo_resume_number_entry\" |" num_of_simple_functions
572 # Number of moderate functions
574 print "| class=\"cyclo_resume_header_entry\" | Number of moderate risk functions"
575 print "| class=\"cyclo_resume_number_entry\" |" num_of_moderate_functions
576 # Number of high functions
578 print "| class=\"cyclo_resume_header_entry\" | Number of high risk functions"
579 print "| class=\"cyclo_resume_number_entry\" |" num_of_high_functions
580 # Number of untestable functions
582 print "| class=\"cyclo_resume_header_entry\" | Number of untestable functions"
583 print "| class=\"cyclo_resume_number_entry\" |" num_of_untestable_functions
587 function wiki_function_cyclo ()
589 print "==Details for all functions=="
593 print "{| class =\"cyclo_ranges_table\""
595 print "| class=\"cyclo_ranges_header_entry\" | "
596 print "| class=\"cyclo_ranges_header_entry\" | Cyclomatic Complexity"
597 print "| class=\"cyclo_ranges_header_entry\" | Risk Evaluation"
600 print "| class=\"cyclo_ranges_entry_simple\" | "
601 print "| class=\"cyclo_ranges_entry\" | 0 - " cyclo_simple_max
602 print "| class=\"cyclo_ranges_entry\" | Simple module, without much risk"
605 print "| class=\"cyclo_ranges_entry_moderate\" | "
606 print "| class=\"cyclo_ranges_entry\" |" cyclo_simple_max + 1 " - " cyclo_moderate_max
607 print "| class=\"cyclo_ranges_entry\" | More complex module, moderate risk"
610 print "| class=\"cyclo_ranges_entry_high\" | "
611 print "| class=\"cyclo_ranges_entry\" |" cyclo_moderate_max + 1 " - " cyclo_high_max
612 print "| class=\"cyclo_ranges_entry\" | Complex module, high risk"
615 print "| class=\"cyclo_ranges_entry_untestable\" | "
616 print "| class=\"cyclo_ranges_entry\" | greater than " cyclo_high_max
617 print "| class=\"cyclo_ranges_entry\" | Untestable module, very high risk"
622 wiki_fnc_table_complete("")
625 function wiki_fnc_table_complete (caption)
627 wiki_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
630 function wiki_fnc_table_abbrev (caption)
632 wiki_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
635 function wiki_fnc_table (caption,
644 print "{| width=\"90%\" class=\"cyclo_function_table\" cellpadding=\"0\" cellspacing=\"0\">"
649 wiki_fnc_header(fname_p,
656 for (nfnc = 1; nfnc < nfuncs; nfnc++)
670 function wiki_fnc_header (fname_p,
681 print "! class=\"cyclo_function_table_header_entry\" | Function Name"
686 print "! class=\"cyclo_function_table_header_entry\" | Modified Cyclo"
691 print "! class=\"cyclo_function_table_header_entry\" | Cyclomatic Complexity"
693 if (num_statements_p)
695 print "! class=\"cyclo_function_table_header_entry\" | Number of Statements"
699 print "! class=\"cyclo_function_table_header_entry\" | Number of Lines"
703 print "! class=\"cyclo_function_table_header_entry\" | First Line"
707 print "! class=\"cyclo_function_table_header_entry\" | Source File"
711 function wiki_fnc (nfnc,
723 trclass = "cyclo_function_entry_simple"
724 if (mcyclo[nfnc] > cyclo_high_max)
726 trclass="cyclo_function_entry_untestable"
728 else if (mcyclo[nfnc] > cyclo_moderate_max)
730 trclass="cyclo_function_entry_high"
732 else if (mcyclo[nfnc] > cyclo_simple_max)
734 trclass="cyclo_function_entry_moderate"
737 print "|- class=\"" trclass "\""
740 print "| class=\"cyclo_function_entry_name\" |" fname
745 print "| class=\"cyclo_function_entry_cyclo\" |" mcyclo[nfnc]
750 print "| class=\"cyclo_function_entry_cyclo\" |" cyclo[nfnc]
752 if (num_statements_p)
754 # Number of statements
755 print "| class=\"cyclo_function_entry_number\" |" num_statements[nfnc]
760 print "| class=\"cyclo_function_entry_number\" |" num_lines[nfnc]
765 print "| class=\"cyclo_function_entry_number\" |" first_line[nfnc]
770 if (source_file_link_tmpl != "")
773 href = source_file_link_tmpl
774 sub(/%FILENAME%/, file[nfnc], href)
778 print "| class=\"cyclo_function_entry_filename\" |" \
779 ((href != "") ? "[" href " " file[nfnc] "]" : "[" file[nfnc] "]")
783 # Scan data from a line
788 fnames[nfuncs] = function_name
791 num_statements[nfuncs] = $3
792 first_line[nfuncs] = $4
793 num_lines[nfuncs] = $5
795 # Build the filename from the file_spec ($6)
796 begin_util_path = index($6, cut_dir)
797 tmpfilename = substr($6, begin_util_path + length(cut_dir))
798 sub(/\([0-9]+\):/, "", tmpfilename)
799 file[nfuncs] = tmpfilename
801 if (mcyclo[nfuncs] > cyclo_simple_max)
803 # Extract function contents to a fn_txt file
806 sub(/\([0-9]+\):/, "", filepath)
809 while ((getline codeline < filepath) > 0)
812 if ((num_line >= first_line[nfuncs]) &&
813 (num_line < first_line[nfuncs] + num_lines[nfuncs]))
815 print codeline > (function_name nfuncs "_fn.txt")
818 close (function_name nfuncs "_fn.txt")
822 # Initial values for statistics variables
825 max_function_length = 0
826 num_of_simple_functions = 0
827 num_of_moderate_functions = 0
828 num_of_high_functions = 0
829 num_of_untestable_functions = 0
834 # Print header (only for html)
835 if (output_lang == "html")
841 if ((output_lang == "html") &&
846 if ((output_lang == "wiki") &&
852 if (output_lang == "html")
854 print "<div class=\"page_title\">" package_name " Cyclomatic Complexity Report</div>"
855 print "<p>Report generated at: <span class=\"report_timestamp\">" strftime() "</div></p>"
857 if (output_lang == "wiki")
859 print "==" package_name " Cyclomatic Complexity Report=="
860 print "Report generated at: '''" strftime() "'''"
863 if (section_global_stats_p)
867 if (output_lang == "html")
871 if (output_lang == "wiki")
876 if (section_function_cyclo_p)
878 if (output_lang == "html")
880 html_function_cyclo()
882 if (output_lang == "wiki")
884 wiki_function_cyclo()
889 if ((output_lang == "html") &&
894 if ((output_lang == "wiki") &&
900 # Print footer (html only)
901 if (output_lang == "html")
907 # End of pmccabe2html