2 # pmccabe2html - pmccabe to html converter
4 # Copyright (C) 2007, 2008 Free Software Foundation, Inc.
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # Written by Jose E. Marchesi <jemarch@gnu.org>.
20 # Adapted for gnulib by Simon Josefsson <simon@josefsson.org>.
21 # Added support for C++ by Giuseppe Scrivano <gscrivano@gnu.org>.
23 # Typical Invocation is from a Makefile.am:
26 # $(PMCCABE) ${top_srcdir}/lib/*.[ch] \
28 # | $(AWK) -f ${top_srcdir}/build-aux/pmccabe2html \
29 # -v lang=html -v name="$(PACKAGE_NAME)" \
30 # -v vcurl="http://git.savannah.gnu.org/gitweb/?p=libidn.git;a=blob;f=%FILENAME%;hb=HEAD" \
31 # -v url="http://www.gnu.org/software/libidn/" \
32 # -v css=../../build-aux/pmccabe.css \
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
60 source_file_link_tmpl = vcurl
65 html_prolog =
"<a href=\"" url
"\">Back to " package_name
" Homepage</a><br/><br/>"
67 html_epilog =
"<hr color=\"black\" size=\"2\"/> \
68 Copyright (c) 2007, 2008 Free Software Foundation Inc."
69 html_doctype =
"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \
70 \"http://www.w3.org/TR/html401/loose.dtd\">"
71 html_comment =
"<!-- Generated by gnulib's pmccabe2html at " systime
() " -->"
72 html_title =
"Cyclomatic Complexity report for " package_name
75 wiki_prolog =
"{{Note|This page has been automatically generated}}"
84 function build_stats
()
86 # Maximum modified cyclo
90 if (mcyclo
[fcn
] > max_mcyclo
)
92 max_mcyclo = mcyclo
[fcn
]
95 if (mcyclo
[fcn
] > cyclo_high_max
)
97 num_of_untestable_functions
++
99 else if (mcyclo
[fcn
] > cyclo_moderate_max
)
101 num_of_high_functions
++
103 else if (mcyclo
[fcn
] > cyclo_simple_max
)
105 num_of_moderate_functions
++
109 num_of_simple_functions
++
114 function html_fnc_table_complete
(caption
)
116 html_fnc_table
(caption
, 1, 0, 1, 1, 1, 0, 1)
119 function html_fnc_table_abbrev
(caption
)
121 html_fnc_table
(caption
, 1, 0, 1, 0, 1, 0, 0)
125 function html_fnc_table
(caption
,
134 print "<table width=\"90%\" class=
\"function_table
\" cellpadding=
\"0\" cellspacing=
\"0\">"
137 print "<caption class=
\"function_table_caption
\">" caption "</caption
>"
139 html_fnc_header(fname_p,
146 for (nfnc = 1; nfnc < nfuncs; nfnc++)
160 function html_header ()
166 print "<title
>" html_title "</title
>"
168 print "<meta name=
\"description
\" content=
\"" html_title "\">"
169 print "<meta name=
\"keywords
\" content=
\"" html_title "\">"
170 print "<meta name=
\"resource
-type
\" content=
\"document
\">"
171 print "<meta name=
\"distribution
\" content=
\"global
\">"
172 print "<meta name=
\"Generator
\" content=
\"pmccabe2html
\">"
173 print "<meta http
-equiv=
\"Content
-Type
\" content=
\"text
/html
; charset=utf
-8\">"
174 print "<script language=
\"javascript
\" type=
\"text
/javascript
\">"
175 print "function show_hide
(idCapa
, idButton
, fuerzaVisibilidad
)\
177 var button = document.getElementById
(idButton
);\
178 var capa = document.getElementById
(idCapa
);\
181 if (fuerzaVisibilidad
&& fuerzaVisibilidad
!=\"\") {\
182 if (fuerzaVisibilidad==
\"visible
\") capa.style.display=
\"\";\
183 else capa.style.display=
\"none
\";\
187 if (capa.style.display ==
\"none
\") {\
188 capa.style.display =
\"\";\
189 button.innerHTML =
\"&uarr
;\";\
191 capa.style.display =
\"none
\";\
192 button.innerHTML =
\"&darr
;\"; \
202 print "<link rel=
\"stylesheet
\" href=
\"" css_url "\" type =
\"text
/css
\" media=
\"screen
\"/>"
206 print "<style type =
\"text
/css
\" media=
\"screen
\">"
208 while ((getline cssline < css) > 0)
217 print "<body lang=
\"en
\" bgcolor=
\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" \
218 vlink=
\"#800080\" alink=\"#FF0000\">"
221 function html_footer
()
227 function html_fnc_header
(fname_p
,
235 print "<tr class=\"function_table_header\">"
239 print "<td class=\"function_table_header_entry\">"
243 print "<td class=\"function_table_header_entry\">"
244 print "Function Name"
250 print "<td class=\"function_table_header_entry\">"
251 print "Modified Cyclo"
257 print "<td class=\"function_table_header_entry\">"
263 if (num_statements_p
)
265 print "<td class=\"function_table_header_entry\">"
273 print "<td class=\"function_table_header_entry\">"
281 print "<td class=\"function_table_header_entry\">"
287 print "<td class=\"function_table_header_entry\">"
295 function html_fnc
(nfun
,
307 trclass =
"function_entry_simple"
308 if (mcyclo
[nfun
] > cyclo_high_max
)
310 trclass=
"function_entry_untestable"
312 else if (mcyclo
[nfun
] > cyclo_moderate_max
)
314 trclass=
"function_entry_high"
316 else if (mcyclo
[nfun
] > cyclo_simple_max
)
318 trclass=
"function_entry_moderate"
321 print "<tr class=\"" trclass
"\">"
324 print "<td class=\"function_entry_filename\">"
325 if (file_p
&& mcyclo
[nfun
] > cyclo_simple_max
)
327 print "<a href=\"javascript:void(0);\" title=\"show/hide function source\" onClick=\"javascript:show_hide('" fname
"_src', '" fname
"_button')\">\
328 <span id=\"" fname
"_button\">↓</span></a>"
336 print "<td class=\"function_entry_name\">"
343 print "<td class=\"function_entry_cyclo\">"
350 print "<td class=\"function_entry_cyclo\">"
354 if (num_statements_p
)
356 # Number of statements
357 print "<td class=\"function_entry_number\">"
358 print num_statements
[nfun
]
364 print "<td class=\"function_entry_number\">"
365 print num_lines
[nfun
]
371 print "<td class=\"function_entry_number\">"
372 print first_line
[nfun
]
378 if (source_file_link_tmpl
!= "")
381 href = source_file_link_tmpl
382 sub(/%
FILENAME%
/, file
[nfun
], href
)
386 print "<td class=\"function_entry_filename\">"
389 print "<a href=\"" href
"\">" file
[nfun
] "</a>"
401 if (mcyclo
[nfun
] > cyclo_simple_max
)
406 if (fname_p
) { num_columns
++ }
407 if (mcyclo_p
) { num_columns
++ }
408 if (cyclo_p
) { num_columns
++ }
409 if (num_statements_p
) { num_columns
++ }
410 if (num_lines_p
) { num_columns
++ }
411 if (first_line_p
) { num_columns
++ }
412 if (file_p
) { num_columns
++ }
414 print "<td colspan=\"" num_columns
"\" height=\"0\">"
415 print "<div id=\"" fname
"_src\" class=\"function_src\" style=\"position: relative; display: none;\">"
416 print "<pre class=\"function_src\">"
418 while ((getline codeline
< (fname nfun
"_fn.txt")) > 0)
420 sub(/\\</, "<", codeline
)
421 sub(/\\>/, ">", codeline
)
422 sub(/&/, "&", codeline
)
426 close(fname nfun
"_fn.txt")
427 system("rm " fname nfun
"_fn.txt")
437 function html_global_stats
()
439 print "<div class=\"section_title\">Resume</div>"
442 print "<table class=\"resume_table\">"
443 # Total number of functions
445 print "<td class=\"resume_header_entry\">"
446 print "Total number of functions"
448 print "<td class=\"resume_number_entry\">"
449 print num_of_functions
452 # Number of simple functions
454 print "<td class=\"resume_header_entry\">"
455 print "Number of low risk functions"
457 print "<td class=\"resume_number_entry\">"
458 print num_of_simple_functions
461 # Number of moderate functions
463 print "<td class=\"resume_header_entry\">"
464 print "Number of moderate risk functions"
466 print "<td class=\"resume_number_entry\">"
467 print num_of_moderate_functions
470 # Number of high functions
472 print "<td class=\"resume_header_entry\">"
473 print "Number of high risk functions"
475 print "<td class=\"resume_number_entry\">"
476 print num_of_high_functions
479 # Number of untestable functions
481 print "<td class=\"resume_header_entry\">"
482 print "Number of untestable functions"
484 print "<td class=\"resume_number_entry\">"
485 print num_of_untestable_functions
492 function html_function_cyclo
()
494 print "<div class=\"section_title\">Details for all functions</div>"
495 print "<p>Used ranges:</p>"
497 print "<table class=\"ranges_table\">"
499 print "<td class=\"ranges_header_entry\">"
502 print "<td class=\"ranges_header_entry\">"
503 print "Cyclomatic Complexity"
505 print "<td class=\"ranges_header_entry\">"
506 print "Risk Evaluation"
511 print "<td class=\"ranges_entry_simple\">"
514 print "<td class=\"ranges_entry\">"
515 print "0 - " cyclo_simple_max
517 print "<td class=\"ranges_entry\">"
518 print "Simple module, without much risk"
523 print "<td class=\"ranges_entry_moderate\">"
526 print "<td class=\"ranges_entry\">"
527 print cyclo_simple_max
+ 1 " - " cyclo_moderate_max
529 print "<td class=\"ranges_entry\">"
530 print "More complex module, moderate risk"
535 print "<td class=\"ranges_entry_high\">"
538 print "<td class=\"ranges_entry\">"
539 print cyclo_moderate_max
+ 1 " - " cyclo_high_max
541 print "<td class=\"ranges_entry\">"
542 print "Complex module, high risk"
547 print "<td class=\"ranges_entry_untestable\">"
550 print "<td class=\"ranges_entry\">"
551 print "greater than " cyclo_high_max
553 print "<td class=\"ranges_entry\">"
554 print "Untestable module, very high risk"
559 html_fnc_table_complete
("")
562 function wiki_global_stats
()
564 print "{| class=\"cyclo_resume_table\""
565 # Total number of functions
567 print "| class=\"cyclo_resume_header_entry\" | Total number of functions"
568 print "| class=\"cyclo_resume_number_entry\" |" num_of_functions
569 # Number of simple functions
571 print "| class=\"cyclo_resume_header_entry\" | Number of low risk functions"
572 print "| class=\"cyclo_resume_number_entry\" |" num_of_simple_functions
573 # Number of moderate functions
575 print "| class=\"cyclo_resume_header_entry\" | Number of moderate risk functions"
576 print "| class=\"cyclo_resume_number_entry\" |" num_of_moderate_functions
577 # Number of high functions
579 print "| class=\"cyclo_resume_header_entry\" | Number of high risk functions"
580 print "| class=\"cyclo_resume_number_entry\" |" num_of_high_functions
581 # Number of untestable functions
583 print "| class=\"cyclo_resume_header_entry\" | Number of untestable functions"
584 print "| class=\"cyclo_resume_number_entry\" |" num_of_untestable_functions
588 function wiki_function_cyclo
()
590 print "==Details for all functions=="
594 print "{| class =\"cyclo_ranges_table\""
596 print "| class=\"cyclo_ranges_header_entry\" | "
597 print "| class=\"cyclo_ranges_header_entry\" | Cyclomatic Complexity"
598 print "| class=\"cyclo_ranges_header_entry\" | Risk Evaluation"
601 print "| class=\"cyclo_ranges_entry_simple\" | "
602 print "| class=\"cyclo_ranges_entry\" | 0 - " cyclo_simple_max
603 print "| class=\"cyclo_ranges_entry\" | Simple module, without much risk"
606 print "| class=\"cyclo_ranges_entry_moderate\" | "
607 print "| class=\"cyclo_ranges_entry\" |" cyclo_simple_max
+ 1 " - " cyclo_moderate_max
608 print "| class=\"cyclo_ranges_entry\" | More complex module, moderate risk"
611 print "| class=\"cyclo_ranges_entry_high\" | "
612 print "| class=\"cyclo_ranges_entry\" |" cyclo_moderate_max
+ 1 " - " cyclo_high_max
613 print "| class=\"cyclo_ranges_entry\" | Complex module, high risk"
616 print "| class=\"cyclo_ranges_entry_untestable\" | "
617 print "| class=\"cyclo_ranges_entry\" | greater than " cyclo_high_max
618 print "| class=\"cyclo_ranges_entry\" | Untestable module, very high risk"
623 wiki_fnc_table_complete
("")
626 function wiki_fnc_table_complete
(caption
)
628 wiki_fnc_table
(caption
, 1, 0, 1, 1, 1, 0, 1)
631 function wiki_fnc_table_abbrev
(caption
)
633 wiki_fnc_table
(caption
, 1, 0, 0, 0, 0, 0, 0)
636 function wiki_fnc_table
(caption
,
645 print "{| width=\"90%\" class=
\"cyclo_function_table
\" cellpadding=
\"0\" cellspacing=
\"0\">"
650 wiki_fnc_header(fname_p,
657 for (nfnc = 1; nfnc < nfuncs; nfnc++)
671 function wiki_fnc_header (fname_p,
682 print "! class=
\"cyclo_function_table_header_entry
\" | Function Name
"
687 print "! class=
\"cyclo_function_table_header_entry
\" | Modified Cyclo
"
692 print "! class=
\"cyclo_function_table_header_entry
\" | Cyclomatic Complexity
"
694 if (num_statements_p)
696 print "! class=
\"cyclo_function_table_header_entry
\" | Number of Statements
"
700 print "! class=
\"cyclo_function_table_header_entry
\" | Number of Lines
"
704 print "! class=
\"cyclo_function_table_header_entry
\" | First Line
"
708 print "! class=
\"cyclo_function_table_header_entry
\" | Source File
"
712 function wiki_fnc (nfnc,
724 trclass = "cyclo_function_entry_simple
"
725 if (mcyclo[nfnc] > cyclo_high_max)
727 trclass="cyclo_function_entry_untestable
"
729 else if (mcyclo[nfnc] > cyclo_moderate_max)
731 trclass="cyclo_function_entry_high
"
733 else if (mcyclo[nfnc] > cyclo_simple_max)
735 trclass="cyclo_function_entry_moderate
"
738 print "|- class=
\"" trclass "\""
741 print "| class=
\"cyclo_function_entry_name
\" |" fname
746 print "| class=
\"cyclo_function_entry_cyclo
\" |" mcyclo[nfnc]
751 print "| class=
\"cyclo_function_entry_cyclo
\" |" cyclo[nfnc]
753 if (num_statements_p)
755 # Number of statements
756 print "| class=
\"cyclo_function_entry_number
\" |" num_statements[nfnc]
761 print "| class=
\"cyclo_function_entry_number
\" |" num_lines[nfnc]
766 print "| class=
\"cyclo_function_entry_number
\" |" first_line[nfnc]
771 if (source_file_link_tmpl != "")
774 href = source_file_link_tmpl
775 sub(/%FILENAME%/, file[nfnc], href)
779 print "| class=
\"cyclo_function_entry_filename
\" |" \
780 ((href != "") ? "[" href " " file[nfnc] "]" : "[" file[nfnc] "]")
784 # Scan data from a line
789 fnames[nfuncs] = function_name
792 num_statements[nfuncs] = $3
793 first_line[nfuncs] = $4
794 num_lines[nfuncs] = $5
796 # Build the filename from the file_spec ($6)
797 begin_util_path = index($6, cut_dir)
798 tmpfilename = substr($6, begin_util_path + length(cut_dir))
799 sub(/\([0-9]+\):/, "", tmpfilename)
800 file[nfuncs] = tmpfilename
802 if (mcyclo[nfuncs] > cyclo_simple_max)
804 # Extract function contents to a fn_txt file
807 sub(/\([0-9]+\):/, "", filepath)
810 while ((getline codeline < filepath) > 0)
813 if ((num_line >= first_line[nfuncs]) &&
814 (num_line < first_line[nfuncs] + num_lines[nfuncs]))
816 print codeline > (function_name nfuncs "_fn.txt
")
819 close (function_name nfuncs "_fn.txt
")
823 # Initial values for statistics variables
826 max_function_length = 0
827 num_of_simple_functions = 0
828 num_of_moderate_functions = 0
829 num_of_high_functions = 0
830 num_of_untestable_functions = 0
835 # Print header (only for html)
836 if (output_lang == "html
")
842 if ((output_lang == "html
") &&
847 if ((output_lang == "wiki
") &&
853 if (output_lang == "html
")
855 print "<div class=
\"page_title
\">" package_name " Cyclomatic Complexity Report
</div
>"
856 print "<p
>Report generated at
: <span class=
\"report_timestamp
\">" strftime() "</div
></p
>"
858 if (output_lang == "wiki
")
860 print "==
" package_name " Cyclomatic Complexity Report==
"
861 print "Report generated at
: '''" strftime() "'''"
864 if (section_global_stats_p)
868 if (output_lang == "html
")
872 if (output_lang == "wiki
")
877 if (section_function_cyclo_p)
879 if (output_lang == "html
")
881 html_function_cyclo()
883 if (output_lang == "wiki
")
885 wiki_function_cyclo()
890 if ((output_lang == "html
") &&
895 if ((output_lang == "wiki
") &&
901 # Print footer (html only)
902 if (output_lang == "html
")
908 # End of pmccabe2html