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/" \
32 # mv tmp libidn-cyclo.html
34 # The variables available are:
35 # lang output language, either 'html' or 'wiki'
37 # url link to project's home page
38 # vcurl URL to version controlled source code browser,
39 # a %FILENAME% in the string is replaced with the relative
42 # Prologue & configuration
44 section_global_stats_p = 1
45 section_function_cyclo_p = 1
53 cyclo_moderate_max = 20
56 source_file_link_tmpl = vcurl
61 html_prolog = "<a href=\"" url "\">Back to " package_name " Homepage</a><br/><br/>"
63 html_epilog = "<hr color=\"black\" size=\"2\"/> \
64 Copyright (c) 2007, 2008 Free Software Foundation Inc."
65 css_url = "pmccabe.css"
66 html_doctype = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \
67 \"http://www.w3.org/TR/html401/loose.dtd\">"
68 html_comment = "<!-- Generated by gnulib's pmccabe2html at " systime() " -->"
69 html_title = "Cyclomatic Complexity report for " package_name
72 wiki_prolog = "{{Note|This page has been automatically generated}}"
81 function build_stats()
83 # Maximum modified cyclo
87 if (mcyclo[fcn] > max_mcyclo)
89 max_mcyclo = mcyclo[fcn]
92 if (mcyclo[fcn] > cyclo_high_max)
94 num_of_untestable_functions++
96 else if (mcyclo[fcn] > cyclo_moderate_max)
98 num_of_high_functions++
100 else if (mcyclo[fcn] > cyclo_simple_max)
102 num_of_moderate_functions++
106 num_of_simple_functions++
111 function html_fnc_table_complete (caption)
113 html_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
116 function html_fnc_table_abbrev (caption)
118 html_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
122 function html_fnc_table (caption,
131 print "<table width=\"90%\" class=\"function_table\" cellpadding=\"0\" cellspacing=\"0\">"
134 print "<caption class=\"function_table_caption\">" caption "</caption>"
136 html_fnc_header(fname_p,
143 for (nfnc = 1; nfnc < nfuncs; nfnc++)
158 function html_header ()
164 print "<title>" html_title "</title>"
166 print "<meta name=\"description\" content=\"" html_title "\">"
167 print "<meta name=\"keywords\" content=\"" html_title "\">"
168 print "<meta name=\"resource-type\" content=\"document\">"
169 print "<meta name=\"distribution\" content=\"global\">"
170 print "<meta name=\"Generator\" content=\"pmccabe2html\">"
171 print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
172 print "<script language=\"javascript\" type=\"text/javascript\">"
173 print "function show_hide(idCapa, idButton, fuerzaVisibilidad)\
175 var button = document.getElementById(idButton);\
176 var capa = document.getElementById(idCapa);\
179 if (fuerzaVisibilidad && fuerzaVisibilidad!=\"\") {\
180 if (fuerzaVisibilidad==\"visible\") capa.style.display=\"\";\
181 else capa.style.display=\"none\";\
185 if (capa.style.display == \"none\") {\
186 capa.style.display = \"\";\
187 button.innerHTML = \"↑\";\
189 capa.style.display = \"none\";\
190 button.innerHTML = \"↓\"; \
200 print "<link rel=\"stylesheet\" href=\"" css_url "\" type =\"text/css\" media=\"screen\"/>"
203 print "<body lang=\"en\" bgcolor=\"#FFFFFF\" text=\"#000000\" link=\"#0000FF\" \
204 vlink=\"#800080\" alink=\"#FF0000\">"
207 function html_footer ()
213 function html_fnc_header (fname_p,
221 print "<tr class=\"function_table_header\">"
225 print "<td class=\"function_table_header_entry\">"
229 print "<td class=\"function_table_header_entry\">"
230 print "Function Name"
236 print "<td class=\"function_table_header_entry\">"
237 print "Modified Cyclo"
243 print "<td class=\"function_table_header_entry\">"
249 if (num_statements_p)
251 print "<td class=\"function_table_header_entry\">"
259 print "<td class=\"function_table_header_entry\">"
267 print "<td class=\"function_table_header_entry\">"
273 print "<td class=\"function_table_header_entry\">"
281 function html_fnc (fname,
291 trclass = "function_entry_simple"
292 if (mcyclo[fname] > cyclo_high_max)
294 trclass="function_entry_untestable"
296 else if (mcyclo[fname] > cyclo_moderate_max)
298 trclass="function_entry_high"
300 else if (mcyclo[fname] > cyclo_simple_max)
302 trclass="function_entry_moderate"
305 print "<tr class=\"" trclass "\">"
308 print "<td class=\"function_entry_filename\">"
309 if (mcyclo[fname] > cyclo_simple_max)
311 print "<a href=\"javascript:void(0);\" title=\"show/hide function source\" onClick=\"javascript:show_hide('" fname "_src', '" fname "_button')\">\
312 <span id=\"" fname "_button\">↓</span></a>"
320 print "<td class=\"function_entry_name\">"
327 print "<td class=\"function_entry_cyclo\">"
334 print "<td class=\"function_entry_cyclo\">"
338 if (num_statements_p)
340 # Number of statements
341 print "<td class=\"function_entry_number\">"
342 print num_statements[fname]
348 print "<td class=\"function_entry_number\">"
349 print num_lines[fname]
355 print "<td class=\"function_entry_number\">"
356 print first_line[fname]
362 if (source_file_link_tmpl != "")
365 href = source_file_link_tmpl
366 sub(/%FILENAME%/, file[fname], href)
370 print "<td class=\"function_entry_filename\">"
373 print "<a href=\"" href "\">" file[fname] "</a>"
385 if (mcyclo[fname] > cyclo_simple_max)
390 if (fname_p) { num_columns++ }
391 if (mcyclo_p) { num_columns++ }
392 if (cyclo_p) { num_columns++ }
393 if (num_statements_p) { num_columns++ }
394 if (num_lines_p) { num_columns++ }
395 if (first_line_p) { num_columns++ }
396 if (file_p) { num_columns++ }
398 print "<td colspan=\"" num_columns "\" height=\"0\">"
399 print "<div id=\"" fname "_src\" class=\"function_src\" style=\"position: relative; display: none;\">"
400 print "<pre class=\"function_src\">"
401 while ((getline codeline < (fname "_fn.txt")) > 0)
403 sub(/\\</, "<", codeline)
404 sub(/\\>/, ">", codeline)
405 sub(/&/, "&", codeline)
409 close(fname "_fn.txt")
410 system("rm " fname "_fn.txt")
420 function html_global_stats ()
422 print "<div class=\"section_title\">Resume</div>"
425 print "<table class=\"resume_table\">"
426 # Total number of functions
428 print "<td class=\"resume_header_entry\">"
429 print "Total number of functions"
431 print "<td class=\"resume_number_entry\">"
432 print num_of_functions
435 # Number of simple functions
437 print "<td class=\"resume_header_entry\">"
438 print "Number of low risk functions"
440 print "<td class=\"resume_number_entry\">"
441 print num_of_simple_functions
444 # Number of moderate functions
446 print "<td class=\"resume_header_entry\">"
447 print "Number of moderate risk functions"
449 print "<td class=\"resume_number_entry\">"
450 print num_of_moderate_functions
453 # Number of high functions
455 print "<td class=\"resume_header_entry\">"
456 print "Number of high risk functions"
458 print "<td class=\"resume_number_entry\">"
459 print num_of_high_functions
462 # Number of untestable functions
464 print "<td class=\"resume_header_entry\">"
465 print "Number of untestable functions"
467 print "<td class=\"resume_number_entry\">"
468 print num_of_untestable_functions
475 function html_function_cyclo ()
477 print "<div class=\"section_title\">Details for all functions</div>"
478 print "<p>Used ranges:</p>"
480 print "<table class=\"ranges_table\">"
482 print "<td class=\"ranges_header_entry\">"
485 print "<td class=\"ranges_header_entry\">"
486 print "Cyclomatic Complexity"
488 print "<td class=\"ranges_header_entry\">"
489 print "Risk Evaluation"
494 print "<td class=\"ranges_entry_simple\">"
497 print "<td class=\"ranges_entry\">"
498 print "0 - " cyclo_simple_max
500 print "<td class=\"ranges_entry\">"
501 print "Simple module, without much risk"
506 print "<td class=\"ranges_entry_moderate\">"
509 print "<td class=\"ranges_entry\">"
510 print cyclo_simple_max + 1 " - " cyclo_moderate_max
512 print "<td class=\"ranges_entry\">"
513 print "More complex module, moderate risk"
518 print "<td class=\"ranges_entry_high\">"
521 print "<td class=\"ranges_entry\">"
522 print cyclo_moderate_max + 1 " - " cyclo_high_max
524 print "<td class=\"ranges_entry\">"
525 print "Complex module, high risk"
530 print "<td class=\"ranges_entry_untestable\">"
533 print "<td class=\"ranges_entry\">"
534 print "greater than " cyclo_high_max
536 print "<td class=\"ranges_entry\">"
537 print "Untestable module, very high risk"
542 html_fnc_table_complete("")
545 function wiki_global_stats ()
547 print "{| class=\"cyclo_resume_table\""
548 # Total number of functions
550 print "| class=\"cyclo_resume_header_entry\" | Total number of functions"
551 print "| class=\"cyclo_resume_number_entry\" |" num_of_functions
552 # Number of simple functions
554 print "| class=\"cyclo_resume_header_entry\" | Number of low risk functions"
555 print "| class=\"cyclo_resume_number_entry\" |" num_of_simple_functions
556 # Number of moderate functions
558 print "| class=\"cyclo_resume_header_entry\" | Number of moderate risk functions"
559 print "| class=\"cyclo_resume_number_entry\" |" num_of_moderate_functions
560 # Number of high functions
562 print "| class=\"cyclo_resume_header_entry\" | Number of high risk functions"
563 print "| class=\"cyclo_resume_number_entry\" |" num_of_high_functions
564 # Number of untestable functions
566 print "| class=\"cyclo_resume_header_entry\" | Number of untestable functions"
567 print "| class=\"cyclo_resume_number_entry\" |" num_of_untestable_functions
571 function wiki_function_cyclo ()
573 print "==Details for all functions=="
577 print "{| class =\"cyclo_ranges_table\""
579 print "| class=\"cyclo_ranges_header_entry\" | "
580 print "| class=\"cyclo_ranges_header_entry\" | Cyclomatic Complexity"
581 print "| class=\"cyclo_ranges_header_entry\" | Risk Evaluation"
584 print "| class=\"cyclo_ranges_entry_simple\" | "
585 print "| class=\"cyclo_ranges_entry\" | 0 - " cyclo_simple_max
586 print "| class=\"cyclo_ranges_entry\" | Simple module, without much risk"
589 print "| class=\"cyclo_ranges_entry_moderate\" | "
590 print "| class=\"cyclo_ranges_entry\" |" cyclo_simple_max + 1 " - " cyclo_moderate_max
591 print "| class=\"cyclo_ranges_entry\" | More complex module, moderate risk"
594 print "| class=\"cyclo_ranges_entry_high\" | "
595 print "| class=\"cyclo_ranges_entry\" |" cyclo_moderate_max + 1 " - " cyclo_high_max
596 print "| class=\"cyclo_ranges_entry\" | Complex module, high risk"
599 print "| class=\"cyclo_ranges_entry_untestable\" | "
600 print "| class=\"cyclo_ranges_entry\" | greater than " cyclo_high_max
601 print "| class=\"cyclo_ranges_entry\" | Untestable module, very high risk"
606 wiki_fnc_table_complete("")
609 function wiki_fnc_table_complete (caption)
611 wiki_fnc_table(caption, 1, 0, 1, 1, 1, 0, 1)
614 function wiki_fnc_table_abbrev (caption)
616 wiki_fnc_table(caption, 1, 0, 0, 0, 0, 0, 0)
619 function wiki_fnc_table (caption,
628 print "{| width=\"90%\" class=\"cyclo_function_table\" cellpadding=\"0\" cellspacing=\"0\">"
633 wiki_fnc_header(fname_p,
640 for (nfnc = 1; nfnc < nfuncs; nfnc++)
655 function wiki_fnc_header (fname_p,
666 print "! class=\"cyclo_function_table_header_entry\" | Function Name"
671 print "! class=\"cyclo_function_table_header_entry\" | Modified Cyclo"
676 print "! class=\"cyclo_function_table_header_entry\" | Cyclomatic Complexity"
678 if (num_statements_p)
680 print "! class=\"cyclo_function_table_header_entry\" | Number of Statements"
684 print "! class=\"cyclo_function_table_header_entry\" | Number of Lines"
688 print "! class=\"cyclo_function_table_header_entry\" | First Line"
692 print "! class=\"cyclo_function_table_header_entry\" | Source File"
696 function wiki_fnc (fname,
706 trclass = "cyclo_function_entry_simple"
707 if (mcyclo[fname] > cyclo_high_max)
709 trclass="cyclo_function_entry_untestable"
711 else if (mcyclo[fname] > cyclo_moderate_max)
713 trclass="cyclo_function_entry_high"
715 else if (mcyclo[fname] > cyclo_simple_max)
717 trclass="cyclo_function_entry_moderate"
720 print "|- class=\"" trclass "\""
723 print "| class=\"cyclo_function_entry_name\" |" fname
728 print "| class=\"cyclo_function_entry_cyclo\" |" mcyclo[fname]
733 print "| class=\"cyclo_function_entry_cyclo\" |" cyclo[fname]
735 if (num_statements_p)
737 # Number of statements
738 print "| class=\"cyclo_function_entry_number\" |" num_statements[fname]
743 print "| class=\"cyclo_function_entry_number\" |" num_lines[fname]
748 print "| class=\"cyclo_function_entry_number\" |" first_line[fname]
753 if (source_file_link_tmpl != "")
756 href = source_file_link_tmpl
757 sub(/%FILENAME%/, file[fname], href)
761 print "| class=\"cyclo_function_entry_filename\" |" \
762 ((href != "") ? "[" href " " file[fname] "]" : "[" file[fname] "]")
766 # Scan data from a line
771 fnames[nfuncs] = function_name
772 mcyclo[function_name] = $1
773 cyclo[function_name] = $2
774 num_statements[function_name] = $3
775 first_line[function_name] = $4
776 num_lines[function_name] = $5
778 # Build the filename from the file_spec ($6)
779 begin_util_path = index($6, cut_dir)
780 tmpfilename = substr($6, begin_util_path + length(cut_dir))
781 sub(/\([0-9]+\):/, "", tmpfilename)
782 file[function_name] = tmpfilename
784 if (mcyclo[function_name] > cyclo_simple_max)
786 # Extract function contents to a fn_txt file
788 sub(/\([0-9]+\):/, "", filepath)
790 while ((getline codeline < filepath) > 0)
793 if ((num_line >= first_line[function_name]) &&
794 (num_line < first_line[function_name] + num_lines[function_name]))
796 print codeline > (function_name "_fn.txt")
799 close (function_name "_fn.txt")
803 # Initial values for statistics variables
806 max_function_length = 0
807 num_of_simple_functions = 0
808 num_of_moderate_functions = 0
809 num_of_high_functions = 0
810 num_of_untestable_functions = 0
815 # Print header (only for html)
816 if (output_lang == "html")
822 if ((output_lang == "html") &&
827 if ((output_lang == "wiki") &&
833 if (output_lang == "html")
835 print "<div class=\"page_title\">" package_name " Cyclomatic Complexity Report</div>"
836 print "<p>Report generated at: <span class=\"report_timestamp\">" strftime() "</div></p>"
838 if (output_lang == "wiki")
840 print "==" package_name " Cyclomatic Complexity Report=="
841 print "Report generated at: '''" strftime() "'''"
844 if (section_global_stats_p)
848 if (output_lang == "html")
852 if (output_lang == "wiki")
857 if (section_function_cyclo_p)
859 if (output_lang == "html")
861 html_function_cyclo()
863 if (output_lang == "wiki")
865 wiki_function_cyclo()
870 if ((output_lang == "html") &&
875 if ((output_lang == "wiki") &&
881 # Print footer (html only)
882 if (output_lang == "html")
888 # End of pmccabe2html