3 # pmccabe2html - pmccabe to html converter
5 # Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 # Written by Jose E. Marchesi <jemarch@gnu.org>.
21 # Adapted for gnulib by Simon Josefsson <simon@josefsson.org>.
22 # Added support for C++ by Giuseppe Scrivano <gscrivano@gnu.org>.
24 # Typical Invocation is from a Makefile.am:
27 # $(PMCCABE) ${top_srcdir}/lib/*.[ch] \
29 # | $(AWK) -f ${top_srcdir}/build-aux/pmccabe2html \
30 # -v lang=html -v name="$(PACKAGE_NAME)" \
31 # -v vcurl="http://git.savannah.gnu.org/gitweb/?p=libidn.git;a=blob;f=%FILENAME%;hb=HEAD" \
32 # -v url="http://www.gnu.org/software/libidn/" \
33 # -v css=../../build-aux/pmccabe.css \
37 # The variables available are:
38 # lang output language, either 'html' or 'wiki'
40 # url link to project's home page
41 # vcurl URL to version controlled source code browser,
42 # a %FILENAME% in the string is replaced with the relative
44 # css CSS stylesheet filename, included verbatim in HTML output
45 # css_url link to CSS stylesheet, an URL
47 # Prologue & configuration
49 section_global_stats_p = 1
50 section_function_cyclo_p = 1
58 cyclo_moderate_max = 20
61 source_file_link_tmpl = vcurl
66 html_prolog = "<a href=\"" url "\">Back to " package_name " Homepage</a><br/><br/>"
68 html_epilog = "<hr color=\"black\" size=\"2\"/> \
69 Copyright (c) 2007, 2008 Free Software Foundation Inc."
70 html_doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \
71 \"http://www.w3.org/TR/html401/loose.dtd\">"
72 html_comment = "<!-- Generated by gnulib's pmccabe2html at " systime() " -->"
73 html_title = "Cyclomatic Complexity report for " package_name
76 wiki_prolog = "{{Note|This page has been automatically generated}}"
85 function build_stats()
87 # Maximum modified cyclo
91 if (mcyclo[fcn] > max_mcyclo)
93 max_mcyclo = mcyclo[fcn]
96 if (mcyclo[fcn] > cyclo_high_max)
98 num_of_untestable_functions++
100 else if (mcyclo[fcn] > cyclo_moderate_max)
102 num_of_high_functions++
104 else if (mcyclo[fcn] > cyclo_simple_max)
106 num_of_moderate_functions++
110 num_of_simple_functions++
115 function html_fnc_table_complete (caption)
117 html_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
120 function html_fnc_table_abbrev (caption)
122 html_fnc_table(caption, 1, 0, 1, 0, 1, 0, 0)
126 function html_fnc_table (caption,
135 print "<table width=\"90%\" class=\"function_table\" cellpadding=\"0\" cellspacing=\"0\">"
138 print "<caption class=\"function_table_caption\">" caption "</caption>"
140 html_fnc_header(fname_p,
147 for (nfnc = 1; nfnc < nfuncs; nfnc++)
161 function html_header ()
167 print "<title>" html_title "</title>"
169 print "<meta name=\"description\" content=\"" html_title "\">"
170 print "<meta name=\"keywords\" content=\"" html_title "\">"
171 print "<meta name=\"resource-type\" content=\"document\">"
172 print "<meta name=\"distribution\" content=\"global\">"
173 print "<meta name=\"Generator\" content=\"pmccabe2html\">"
174 print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
175 print "<script language=\"javascript\" type=\"text/javascript\">"
176 print "function show_hide(idCapa, idButton, fuerzaVisibilidad)\
178 var button = document.getElementById(idButton);\
179 var capa = document.getElementById(idCapa);\
182 if (fuerzaVisibilidad && fuerzaVisibilidad!=\"\") {\
183 if (fuerzaVisibilidad==\"visible\") capa.style.display=\"\";\
184 else capa.style.display=\"none\";\
188 if (capa.style.display == \"none\") {\
189 capa.style.display = \"\";\
190 button.innerHTML = \"↑\";\
192 capa.style.display = \"none\";\
193 button.innerHTML = \"↓\"; \
203 print "<link rel=\"stylesheet\" href=\"" css_url "\" type =\"text/css\" media=\"screen\"/>"
207 print "<style type =\"text/css\" media=\"screen\">"
209 while ((getline cssline < css) > 0)
218 print "<body lang=\"en\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" \
219 vlink=\"#800080\" alink=\"#FF0000\">"
222 function html_footer ()
228 function html_fnc_header (fname_p,
236 print "<tr class=\"function_table_header\">"
240 print "<td class=\"function_table_header_entry\">"
244 print "<td class=\"function_table_header_entry\">"
245 print "Function Name"
251 print "<td class=\"function_table_header_entry\">"
252 print "Modified Cyclo"
258 print "<td class=\"function_table_header_entry\">"
264 if (num_statements_p)
266 print "<td class=\"function_table_header_entry\">"
274 print "<td class=\"function_table_header_entry\">"
282 print "<td class=\"function_table_header_entry\">"
288 print "<td class=\"function_table_header_entry\">"
296 function html_fnc (nfun,
308 trclass = "function_entry_simple"
309 if (mcyclo[nfun] > cyclo_high_max)
311 trclass="function_entry_untestable"
313 else if (mcyclo[nfun] > cyclo_moderate_max)
315 trclass="function_entry_high"
317 else if (mcyclo[nfun] > cyclo_simple_max)
319 trclass="function_entry_moderate"
322 print "<tr class=\"" trclass "\">"
325 print "<td class=\"function_entry_filename\">"
326 if (file_p && mcyclo[nfun] > cyclo_simple_max)
328 print "<a href=\"javascript:void(0);\" title=\"show/hide function source\" onClick=\"javascript:show_hide('" fname "_src', '" fname "_button')\">\
329 <span id=\"" fname "_button\">↓</span></a>"
337 print "<td class=\"function_entry_name\">"
344 print "<td class=\"function_entry_cyclo\">"
351 print "<td class=\"function_entry_cyclo\">"
355 if (num_statements_p)
357 # Number of statements
358 print "<td class=\"function_entry_number\">"
359 print num_statements[nfun]
365 print "<td class=\"function_entry_number\">"
366 print num_lines[nfun]
372 print "<td class=\"function_entry_number\">"
373 print first_line[nfun]
379 if (source_file_link_tmpl != "")
382 href = source_file_link_tmpl
383 sub(/%FILENAME%/, file[nfun], href)
387 print "<td class=\"function_entry_filename\">"
390 print "<a href=\"" href "\">" file[nfun] "</a>"
402 if (mcyclo[nfun] > cyclo_simple_max)
407 if (fname_p) { num_columns++ }
408 if (mcyclo_p) { num_columns++ }
409 if (cyclo_p) { num_columns++ }
410 if (num_statements_p) { num_columns++ }
411 if (num_lines_p) { num_columns++ }
412 if (first_line_p) { num_columns++ }
413 if (file_p) { num_columns++ }
415 print "<td colspan=\"" num_columns "\" height=\"0\">"
416 print "<div id=\"" fname "_src\" class=\"function_src\" style=\"position: relative; display: none;\">"
417 print "<pre class=\"function_src\">"
419 while ((getline codeline < (fname nfun "_fn.txt")) > 0)
421 sub(/\\</, "<", codeline)
422 sub(/\\>/, ">", codeline)
423 sub(/&/, "&", codeline)
427 close(fname nfun "_fn.txt")
428 system("rm " fname nfun "_fn.txt")
438 function html_global_stats ()
440 print "<div class=\"section_title\">Resume</div>"
443 print "<table class=\"resume_table\">"
444 # Total number of functions
446 print "<td class=\"resume_header_entry\">"
447 print "Total number of functions"
449 print "<td class=\"resume_number_entry\">"
450 print num_of_functions
453 # Number of simple functions
455 print "<td class=\"resume_header_entry\">"
456 print "Number of low risk functions"
458 print "<td class=\"resume_number_entry\">"
459 print num_of_simple_functions
462 # Number of moderate functions
464 print "<td class=\"resume_header_entry\">"
465 print "Number of moderate risk functions"
467 print "<td class=\"resume_number_entry\">"
468 print num_of_moderate_functions
471 # Number of high functions
473 print "<td class=\"resume_header_entry\">"
474 print "Number of high risk functions"
476 print "<td class=\"resume_number_entry\">"
477 print num_of_high_functions
480 # Number of untestable functions
482 print "<td class=\"resume_header_entry\">"
483 print "Number of untestable functions"
485 print "<td class=\"resume_number_entry\">"
486 print num_of_untestable_functions
493 function html_function_cyclo ()
495 print "<div class=\"section_title\">Details for all functions</div>"
496 print "<p>Used ranges:</p>"
498 print "<table class=\"ranges_table\">"
500 print "<td class=\"ranges_header_entry\">"
503 print "<td class=\"ranges_header_entry\">"
504 print "Cyclomatic Complexity"
506 print "<td class=\"ranges_header_entry\">"
507 print "Risk Evaluation"
512 print "<td class=\"ranges_entry_simple\">"
515 print "<td class=\"ranges_entry\">"
516 print "0 - " cyclo_simple_max
518 print "<td class=\"ranges_entry\">"
519 print "Simple module, without much risk"
524 print "<td class=\"ranges_entry_moderate\">"
527 print "<td class=\"ranges_entry\">"
528 print cyclo_simple_max + 1 " - " cyclo_moderate_max
530 print "<td class=\"ranges_entry\">"
531 print "More complex module, moderate risk"
536 print "<td class=\"ranges_entry_high\">"
539 print "<td class=\"ranges_entry\">"
540 print cyclo_moderate_max + 1 " - " cyclo_high_max
542 print "<td class=\"ranges_entry\">"
543 print "Complex module, high risk"
548 print "<td class=\"ranges_entry_untestable\">"
551 print "<td class=\"ranges_entry\">"
552 print "greater than " cyclo_high_max
554 print "<td class=\"ranges_entry\">"
555 print "Untestable module, very high risk"
560 html_fnc_table_complete("")
563 function wiki_global_stats ()
565 print "{| class=\"cyclo_resume_table\""
566 # Total number of functions
568 print "| class=\"cyclo_resume_header_entry\" | Total number of functions"
569 print "| class=\"cyclo_resume_number_entry\" |" num_of_functions
570 # Number of simple functions
572 print "| class=\"cyclo_resume_header_entry\" | Number of low risk functions"
573 print "| class=\"cyclo_resume_number_entry\" |" num_of_simple_functions
574 # Number of moderate functions
576 print "| class=\"cyclo_resume_header_entry\" | Number of moderate risk functions"
577 print "| class=\"cyclo_resume_number_entry\" |" num_of_moderate_functions
578 # Number of high functions
580 print "| class=\"cyclo_resume_header_entry\" | Number of high risk functions"
581 print "| class=\"cyclo_resume_number_entry\" |" num_of_high_functions
582 # Number of untestable functions
584 print "| class=\"cyclo_resume_header_entry\" | Number of untestable functions"
585 print "| class=\"cyclo_resume_number_entry\" |" num_of_untestable_functions
589 function wiki_function_cyclo ()
591 print "==Details for all functions=="
595 print "{| class =\"cyclo_ranges_table\""
597 print "| class=\"cyclo_ranges_header_entry\" | "
598 print "| class=\"cyclo_ranges_header_entry\" | Cyclomatic Complexity"
599 print "| class=\"cyclo_ranges_header_entry\" | Risk Evaluation"
602 print "| class=\"cyclo_ranges_entry_simple\" | "
603 print "| class=\"cyclo_ranges_entry\" | 0 - " cyclo_simple_max
604 print "| class=\"cyclo_ranges_entry\" | Simple module, without much risk"
607 print "| class=\"cyclo_ranges_entry_moderate\" | "
608 print "| class=\"cyclo_ranges_entry\" |" cyclo_simple_max + 1 " - " cyclo_moderate_max
609 print "| class=\"cyclo_ranges_entry\" | More complex module, moderate risk"
612 print "| class=\"cyclo_ranges_entry_high\" | "
613 print "| class=\"cyclo_ranges_entry\" |" cyclo_moderate_max + 1 " - " cyclo_high_max
614 print "| class=\"cyclo_ranges_entry\" | Complex module, high risk"
617 print "| class=\"cyclo_ranges_entry_untestable\" | "
618 print "| class=\"cyclo_ranges_entry\" | greater than " cyclo_high_max
619 print "| class=\"cyclo_ranges_entry\" | Untestable module, very high risk"
624 wiki_fnc_table_complete("")
627 function wiki_fnc_table_complete (caption)
629 wiki_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
632 function wiki_fnc_table_abbrev (caption)
634 wiki_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
637 function wiki_fnc_table (caption,
646 print "{| width=\"90%\" class=\"cyclo_function_table\" cellpadding=\"0\" cellspacing=\"0\">"
651 wiki_fnc_header(fname_p,
658 for (nfnc = 1; nfnc < nfuncs; nfnc++)
672 function wiki_fnc_header (fname_p,
683 print "! class=\"cyclo_function_table_header_entry\" | Function Name"
688 print "! class=\"cyclo_function_table_header_entry\" | Modified Cyclo"
693 print "! class=\"cyclo_function_table_header_entry\" | Cyclomatic Complexity"
695 if (num_statements_p)
697 print "! class=\"cyclo_function_table_header_entry\" | Number of Statements"
701 print "! class=\"cyclo_function_table_header_entry\" | Number of Lines"
705 print "! class=\"cyclo_function_table_header_entry\" | First Line"
709 print "! class=\"cyclo_function_table_header_entry\" | Source File"
713 function wiki_fnc (nfnc,
725 trclass = "cyclo_function_entry_simple"
726 if (mcyclo[nfnc] > cyclo_high_max)
728 trclass="cyclo_function_entry_untestable"
730 else if (mcyclo[nfnc] > cyclo_moderate_max)
732 trclass="cyclo_function_entry_high"
734 else if (mcyclo[nfnc] > cyclo_simple_max)
736 trclass="cyclo_function_entry_moderate"
739 print "|- class=\"" trclass "\""
742 print "| class=\"cyclo_function_entry_name\" |" fname
747 print "| class=\"cyclo_function_entry_cyclo\" |" mcyclo[nfnc]
752 print "| class=\"cyclo_function_entry_cyclo\" |" cyclo[nfnc]
754 if (num_statements_p)
756 # Number of statements
757 print "| class=\"cyclo_function_entry_number\" |" num_statements[nfnc]
762 print "| class=\"cyclo_function_entry_number\" |" num_lines[nfnc]
767 print "| class=\"cyclo_function_entry_number\" |" first_line[nfnc]
772 if (source_file_link_tmpl != "")
775 href = source_file_link_tmpl
776 sub(/%FILENAME%/, file[nfnc], href)
780 print "| class=\"cyclo_function_entry_filename\" |" \
781 ((href != "") ? "[" href " " file[nfnc] "]" : "[" file[nfnc] "]")
785 # Scan data from a line
790 fnames[nfuncs] = function_name
793 num_statements[nfuncs] = $3
794 first_line[nfuncs] = $4
795 num_lines[nfuncs] = $5
797 # Build the filename from the file_spec ($6)
798 begin_util_path = index($6, cut_dir)
799 tmpfilename = substr($6, begin_util_path + length(cut_dir))
800 sub(/\([0-9]+\):/, "", tmpfilename)
801 file[nfuncs] = tmpfilename
803 if (mcyclo[nfuncs] > cyclo_simple_max)
805 # Extract function contents to a fn_txt file
808 sub(/\([0-9]+\):/, "", filepath)
811 while ((getline codeline < filepath) > 0)
814 if ((num_line >= first_line[nfuncs]) &&
815 (num_line < first_line[nfuncs] + num_lines[nfuncs]))
817 print codeline > (function_name nfuncs "_fn.txt")
820 close (function_name nfuncs "_fn.txt")
824 # Initial values for statistics variables
827 max_function_length = 0
828 num_of_simple_functions = 0
829 num_of_moderate_functions = 0
830 num_of_high_functions = 0
831 num_of_untestable_functions = 0
836 # Print header (only for html)
837 if (output_lang == "html")
843 if ((output_lang == "html") &&
848 if ((output_lang == "wiki") &&
854 if (output_lang == "html")
856 print "<div class=\"page_title\">" package_name " Cyclomatic Complexity Report</div>"
857 print "<p>Report generated at: <span class=\"report_timestamp\">" strftime() "</div></p>"
859 if (output_lang == "wiki")
861 print "==" package_name " Cyclomatic Complexity Report=="
862 print "Report generated at: '''" strftime() "'''"
865 if (section_global_stats_p)
869 if (output_lang == "html")
873 if (output_lang == "wiki")
878 if (section_function_cyclo_p)
880 if (output_lang == "html")
882 html_function_cyclo()
884 if (output_lang == "wiki")
886 wiki_function_cyclo()
891 if ((output_lang == "html") &&
896 if ((output_lang == "wiki") &&
902 # Print footer (html only)
903 if (output_lang == "html")
909 # End of pmccabe2html