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>.
22 # Typical Invocation is from a Makefile.am:
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=libidn.git;a=blob;f=%FILENAME%;hb=HEAD" \
30 # -v url="http://www.gnu.org/software/libidn/" \
31 # -v css=../../build-aux/pmccabe.css \
35 # The variables available are:
36 # lang output language, either 'html' or 'wiki'
38 # url link to project's home page
39 # vcurl URL to version controlled source code browser,
40 # a %FILENAME% in the string is replaced with the relative
42 # css CSS stylesheet filename, included verbatim in HTML output
43 # css_url link to CSS stylesheet, an URL
45 # Prologue & configuration
47 section_global_stats_p = 1
48 section_function_cyclo_p = 1
56 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, 0, 0, 0, 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++)
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 = \"↑\";\
191 capa.style.display = \"none\";\
192 button.innerHTML = \"↓\"; \
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 (fname,
305 trclass = "function_entry_simple"
306 if (mcyclo[fname] > cyclo_high_max)
308 trclass="function_entry_untestable"
310 else if (mcyclo[fname] > cyclo_moderate_max)
312 trclass="function_entry_high"
314 else if (mcyclo[fname] > cyclo_simple_max)
316 trclass="function_entry_moderate"
319 print "<tr class=\"" trclass "\">"
322 print "<td class=\"function_entry_filename\">"
323 if (mcyclo[fname] > cyclo_simple_max)
325 print "<a href=\"javascript:void(0);\" title=\"show/hide function source\" onClick=\"javascript:show_hide('" fname "_src', '" fname "_button')\">\
326 <span id=\"" fname "_button\">↓</span></a>"
334 print "<td class=\"function_entry_name\">"
341 print "<td class=\"function_entry_cyclo\">"
348 print "<td class=\"function_entry_cyclo\">"
352 if (num_statements_p)
354 # Number of statements
355 print "<td class=\"function_entry_number\">"
356 print num_statements[fname]
362 print "<td class=\"function_entry_number\">"
363 print num_lines[fname]
369 print "<td class=\"function_entry_number\">"
370 print first_line[fname]
376 if (source_file_link_tmpl != "")
379 href = source_file_link_tmpl
380 sub(/%FILENAME%/, file[fname], href)
384 print "<td class=\"function_entry_filename\">"
387 print "<a href=\"" href "\">" file[fname] "</a>"
399 if (mcyclo[fname] > cyclo_simple_max)
404 if (fname_p) { num_columns++ }
405 if (mcyclo_p) { num_columns++ }
406 if (cyclo_p) { num_columns++ }
407 if (num_statements_p) { num_columns++ }
408 if (num_lines_p) { num_columns++ }
409 if (first_line_p) { num_columns++ }
410 if (file_p) { num_columns++ }
412 print "<td colspan=\"" num_columns "\" height=\"0\">"
413 print "<div id=\"" fname "_src\" class=\"function_src\" style=\"position: relative; display: none;\">"
414 print "<pre class=\"function_src\">"
415 while ((getline codeline < (fname "_fn.txt")) > 0)
417 sub(/\\</, "<", codeline)
418 sub(/\\>/, ">", codeline)
419 sub(/&/, "&", codeline)
423 close(fname "_fn.txt")
424 system("rm " fname "_fn.txt")
434 function html_global_stats ()
436 print "<div class=\"section_title\">Resume</div>"
439 print "<table class=\"resume_table\">"
440 # Total number of functions
442 print "<td class=\"resume_header_entry\">"
443 print "Total number of functions"
445 print "<td class=\"resume_number_entry\">"
446 print num_of_functions
449 # Number of simple functions
451 print "<td class=\"resume_header_entry\">"
452 print "Number of low risk functions"
454 print "<td class=\"resume_number_entry\">"
455 print num_of_simple_functions
458 # Number of moderate functions
460 print "<td class=\"resume_header_entry\">"
461 print "Number of moderate risk functions"
463 print "<td class=\"resume_number_entry\">"
464 print num_of_moderate_functions
467 # Number of high functions
469 print "<td class=\"resume_header_entry\">"
470 print "Number of high risk functions"
472 print "<td class=\"resume_number_entry\">"
473 print num_of_high_functions
476 # Number of untestable functions
478 print "<td class=\"resume_header_entry\">"
479 print "Number of untestable functions"
481 print "<td class=\"resume_number_entry\">"
482 print num_of_untestable_functions
489 function html_function_cyclo ()
491 print "<div class=\"section_title\">Details for all functions</div>"
492 print "<p>Used ranges:</p>"
494 print "<table class=\"ranges_table\">"
496 print "<td class=\"ranges_header_entry\">"
499 print "<td class=\"ranges_header_entry\">"
500 print "Cyclomatic Complexity"
502 print "<td class=\"ranges_header_entry\">"
503 print "Risk Evaluation"
508 print "<td class=\"ranges_entry_simple\">"
511 print "<td class=\"ranges_entry\">"
512 print "0 - " cyclo_simple_max
514 print "<td class=\"ranges_entry\">"
515 print "Simple module, without much risk"
520 print "<td class=\"ranges_entry_moderate\">"
523 print "<td class=\"ranges_entry\">"
524 print cyclo_simple_max + 1 " - " cyclo_moderate_max
526 print "<td class=\"ranges_entry\">"
527 print "More complex module, moderate risk"
532 print "<td class=\"ranges_entry_high\">"
535 print "<td class=\"ranges_entry\">"
536 print cyclo_moderate_max + 1 " - " cyclo_high_max
538 print "<td class=\"ranges_entry\">"
539 print "Complex module, high risk"
544 print "<td class=\"ranges_entry_untestable\">"
547 print "<td class=\"ranges_entry\">"
548 print "greater than " cyclo_high_max
550 print "<td class=\"ranges_entry\">"
551 print "Untestable module, very high risk"
556 html_fnc_table_complete("")
559 function wiki_global_stats ()
561 print "{| class=\"cyclo_resume_table\""
562 # Total number of functions
564 print "| class=\"cyclo_resume_header_entry\" | Total number of functions"
565 print "| class=\"cyclo_resume_number_entry\" |" num_of_functions
566 # Number of simple functions
568 print "| class=\"cyclo_resume_header_entry\" | Number of low risk functions"
569 print "| class=\"cyclo_resume_number_entry\" |" num_of_simple_functions
570 # Number of moderate functions
572 print "| class=\"cyclo_resume_header_entry\" | Number of moderate risk functions"
573 print "| class=\"cyclo_resume_number_entry\" |" num_of_moderate_functions
574 # Number of high functions
576 print "| class=\"cyclo_resume_header_entry\" | Number of high risk functions"
577 print "| class=\"cyclo_resume_number_entry\" |" num_of_high_functions
578 # Number of untestable functions
580 print "| class=\"cyclo_resume_header_entry\" | Number of untestable functions"
581 print "| class=\"cyclo_resume_number_entry\" |" num_of_untestable_functions
585 function wiki_function_cyclo ()
587 print "==Details for all functions=="
591 print "{| class =\"cyclo_ranges_table\""
593 print "| class=\"cyclo_ranges_header_entry\" | "
594 print "| class=\"cyclo_ranges_header_entry\" | Cyclomatic Complexity"
595 print "| class=\"cyclo_ranges_header_entry\" | Risk Evaluation"
598 print "| class=\"cyclo_ranges_entry_simple\" | "
599 print "| class=\"cyclo_ranges_entry\" | 0 - " cyclo_simple_max
600 print "| class=\"cyclo_ranges_entry\" | Simple module, without much risk"
603 print "| class=\"cyclo_ranges_entry_moderate\" | "
604 print "| class=\"cyclo_ranges_entry\" |" cyclo_simple_max + 1 " - " cyclo_moderate_max
605 print "| class=\"cyclo_ranges_entry\" | More complex module, moderate risk"
608 print "| class=\"cyclo_ranges_entry_high\" | "
609 print "| class=\"cyclo_ranges_entry\" |" cyclo_moderate_max + 1 " - " cyclo_high_max
610 print "| class=\"cyclo_ranges_entry\" | Complex module, high risk"
613 print "| class=\"cyclo_ranges_entry_untestable\" | "
614 print "| class=\"cyclo_ranges_entry\" | greater than " cyclo_high_max
615 print "| class=\"cyclo_ranges_entry\" | Untestable module, very high risk"
620 wiki_fnc_table_complete("")
623 function wiki_fnc_table_complete (caption)
625 wiki_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
628 function wiki_fnc_table_abbrev (caption)
630 wiki_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
633 function wiki_fnc_table (caption,
642 print "{| width=\"90%\" class=\"cyclo_function_table\" cellpadding=\"0\" cellspacing=\"0\">"
647 wiki_fnc_header(fname_p,
654 for (nfnc = 1; nfnc < nfuncs; nfnc++)
669 function wiki_fnc_header (fname_p,
680 print "! class=\"cyclo_function_table_header_entry\" | Function Name"
685 print "! class=\"cyclo_function_table_header_entry\" | Modified Cyclo"
690 print "! class=\"cyclo_function_table_header_entry\" | Cyclomatic Complexity"
692 if (num_statements_p)
694 print "! class=\"cyclo_function_table_header_entry\" | Number of Statements"
698 print "! class=\"cyclo_function_table_header_entry\" | Number of Lines"
702 print "! class=\"cyclo_function_table_header_entry\" | First Line"
706 print "! class=\"cyclo_function_table_header_entry\" | Source File"
710 function wiki_fnc (fname,
720 trclass = "cyclo_function_entry_simple"
721 if (mcyclo[fname] > cyclo_high_max)
723 trclass="cyclo_function_entry_untestable"
725 else if (mcyclo[fname] > cyclo_moderate_max)
727 trclass="cyclo_function_entry_high"
729 else if (mcyclo[fname] > cyclo_simple_max)
731 trclass="cyclo_function_entry_moderate"
734 print "|- class=\"" trclass "\""
737 print "| class=\"cyclo_function_entry_name\" |" fname
742 print "| class=\"cyclo_function_entry_cyclo\" |" mcyclo[fname]
747 print "| class=\"cyclo_function_entry_cyclo\" |" cyclo[fname]
749 if (num_statements_p)
751 # Number of statements
752 print "| class=\"cyclo_function_entry_number\" |" num_statements[fname]
757 print "| class=\"cyclo_function_entry_number\" |" num_lines[fname]
762 print "| class=\"cyclo_function_entry_number\" |" first_line[fname]
767 if (source_file_link_tmpl != "")
770 href = source_file_link_tmpl
771 sub(/%FILENAME%/, file[fname], href)
775 print "| class=\"cyclo_function_entry_filename\" |" \
776 ((href != "") ? "[" href " " file[fname] "]" : "[" file[fname] "]")
780 # Scan data from a line
785 fnames[nfuncs] = function_name
786 mcyclo[function_name] = $1
787 cyclo[function_name] = $2
788 num_statements[function_name] = $3
789 first_line[function_name] = $4
790 num_lines[function_name] = $5
792 # Build the filename from the file_spec ($6)
793 begin_util_path = index($6, cut_dir)
794 tmpfilename = substr($6, begin_util_path + length(cut_dir))
795 sub(/\([0-9]+\):/, "", tmpfilename)
796 file[function_name] = tmpfilename
798 if (mcyclo[function_name] > cyclo_simple_max)
800 # Extract function contents to a fn_txt file
802 sub(/\([0-9]+\):/, "", filepath)
804 while ((getline codeline < filepath) > 0)
807 if ((num_line >= first_line[function_name]) &&
808 (num_line < first_line[function_name] + num_lines[function_name]))
810 print codeline > (function_name "_fn.txt")
813 close (function_name "_fn.txt")
817 # Initial values for statistics variables
820 max_function_length = 0
821 num_of_simple_functions = 0
822 num_of_moderate_functions = 0
823 num_of_high_functions = 0
824 num_of_untestable_functions = 0
829 # Print header (only for html)
830 if (output_lang == "html")
836 if ((output_lang == "html") &&
841 if ((output_lang == "wiki") &&
847 if (output_lang == "html")
849 print "<div class=\"page_title\">" package_name " Cyclomatic Complexity Report</div>"
850 print "<p>Report generated at: <span class=\"report_timestamp\">" strftime() "</div></p>"
852 if (output_lang == "wiki")
854 print "==" package_name " Cyclomatic Complexity Report=="
855 print "Report generated at: '''" strftime() "'''"
858 if (section_global_stats_p)
862 if (output_lang == "html")
866 if (output_lang == "wiki")
871 if (section_function_cyclo_p)
873 if (output_lang == "html")
875 html_function_cyclo()
877 if (output_lang == "wiki")
879 wiki_function_cyclo()
884 if ((output_lang == "html") &&
889 if ((output_lang == "wiki") &&
895 # Print footer (html only)
896 if (output_lang == "html")
902 # End of pmccabe2html