home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume42 / ccount / part03 < prev    next >
Internet Message Format  |  1994-03-29  |  46KB

  1. From: prechelt@ira.uka.de (Lutz Prechelt)
  2. Newsgroups: comp.sources.misc
  3. Subject: v42i022:  ccount - syntactic readability analysis tool, Part03/03
  4. Date: 29 Mar 1994 20:37:22 -0600
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <2naol2$ga3@sparky.sterling.com>
  9. X-Md4-Signature: f6083da242a7b94b956b86f80ac8be13
  10.  
  11. Submitted-by: prechelt@ira.uka.de (Lutz Prechelt)
  12. Posting-number: Volume 42, Issue 22
  13. Archive-name: ccount/part03
  14. Environment: Perl, sh
  15.  
  16. #! /bin/sh
  17. # This is a shell archive.  Remove anything before this line, then feed it
  18. # into a shell via "sh file" or similar.  To overwrite existing files,
  19. # type "sh file -c".
  20. # Contents:  Ccount/README.2 Ccount/statty Ccount/stattyB
  21. #   Ccount/stattyCSE Ccount/stattyF Ccount/stattyM
  22. # Wrapped by kent@sparky on Thu Mar 24 20:42:23 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 3 (of 3)."'
  26. if test -f 'Ccount/README.2' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'Ccount/README.2'\"
  28. else
  29.   echo shar: Extracting \"'Ccount/README.2'\" \(8697 characters\)
  30.   sed "s/^X//" >'Ccount/README.2' <<'END_OF_FILE'
  31. X*****************************************************************************
  32. X
  33. X              R E A D M E  FILE  of  STATISTICAL  T O O L S
  34. X
  35. X*****************************************************************************
  36. X
  37. XAuthor: Joerg Lawrenz, Universitaet Karlsruhe
  38. XDate:   93/12/1
  39. X
  40. X
  41. X=============================================================================
  42. X1. Tools for statistical analysis of 'ccount' outputs
  43. X=============================================================================
  44. X
  45. XThe following PERL programs read data files in 'ccount' output format and
  46. Xgive statistical reports about modules, functions, blocks, control structures
  47. Xand expressions of C source files:
  48. X
  49. X    stattyM      -->   module report
  50. X    stattyF      -->   function report
  51. X    stattyCSE    -->   control structures & expression report
  52. X    stattyB      -->   block report
  53. X    statty       -->   all reports
  54. X
  55. XNote: Before using these tools you possibly have to change the PERL path
  56. Xin the first line of each tool script.
  57. X
  58. X
  59. XAll the reports have the format of a table and they only differ from each
  60. Xother in the values and in the first column where are, one per line, the
  61. Xattributes (e.g. nesting depth) of an object (e.g. if-statement).
  62. XTo the right of each attribute you find 17 values:
  63. X
  64. X    1. average
  65. X    2. standard deviation
  66. X    3. maximum
  67. X    4. 25%-quantile
  68. X    5. exact percentage of the above
  69. X    6. 50%-quantile
  70. X    7. exact percentage of the above
  71. X    8. 75%-quantile
  72. X    9. exact percentage of the above
  73. X       10. 90%-quantile
  74. X       11. exact percentage of the above
  75. X       12. 95%-quantile
  76. X       13. exact percentage of the above
  77. X       14. 98%-quantile
  78. X       15. exact percentage of the above
  79. X       16. 99%-quantile
  80. X       17. exact percentage of the above
  81. X
  82. XBecause of discrete values, quantiles can only be approximated. Therefore a
  83. Xx%-quantile here is that attribute value (starting by zero) by which the
  84. Xaccumulated frequency (in percent) of an object is equal or just greater
  85. Xthan x%. In order to estimate deviations, the exact percentage is indicated
  86. Xfor each quantile.
  87. XLet us assume for example that in the module report the 50%-quantile (median)
  88. Xof the number of functions is 2 and the exact according percentage is 54.4%.
  89. XThat means that 54.4% of all modules have one or two functions, and less 
  90. Xthan half the modules have one function.
  91. X
  92. XIn the first line of each report there is indicated the path from which the 
  93. Xtool producing the according report was started. You will find also the name
  94. Xof the first and the last '*.out'-file of all files that were regarded.
  95. X
  96. XAll reports are 143 columns wide.
  97. X
  98. X=============================================================================
  99. X2. Further details about the individual reports
  100. X=============================================================================
  101. X
  102. XSee also 'README.1', section 4: output format of 'ccount' program.
  103. X(-> nesting depth, operators and block length)
  104. X
  105. XThe numbers of the objects examined by the respective tool are added at the
  106. Xend of the report.
  107. X
  108. X
  109. XI. MODULE REPORT
  110. X-----------------
  111. X
  112. X    Usage:  stattyM  report-filename  [ + exclude-files - ]  input-files
  113. X
  114. X    You can exclude certain files from byte and line count statistics
  115. X        by enclosing their names in '+' and '-'. The affected
  116. X    attributes are marked with '~' below.
  117. X    The number of the excluded files is added at the end of the report.
  118. X    Note that you have to list the excluded files as normal input 
  119. X    files again in the last part of the command line.
  120. X
  121. X    The following module attributes are considered:
  122. X
  123. X         1. Length (in bytes) ~
  124. X         2. Length (in lines) ~
  125. X         3. Average line length (in bytes) ~
  126. X
  127. X         4. Comments (in bytes) ~
  128. X         5. Preprocessor comments (in bytes) ~
  129. X                   (see 'README.1', 2.2)
  130. X         6. Bytes of relevant symbols and words ~
  131. X              (i.e. identifier, symbols, keywords and
  132. X                       preprocessor directives)
  133. X         7. Bytes of 'blanks' ~
  134. X              (i.e. blanks, carriage returns, tabs ...)
  135. X
  136. X         8. Portion of comment (in percent) ~
  137. X         9. Portion of preprocessor comment (in percent) ~
  138. X        10. Portion of relevant symbols and words (in percent) ~
  139. X        11. Portion of 'blanks' (in percent) ~
  140. X
  141. X        12. Number of identifier uses
  142. X        13. Total accumulated length of identifier uses (in bytes)
  143. X
  144. X        14. Number of keyword or symbol uses
  145. X        15. Total accumulated length of keyword/symbol uses (in bytes)
  146. X
  147. X        16. Number of preprocessor directives
  148. X        17. Total accumulated length of preproc. directives (in bytes)
  149. X
  150. X        18. Total number of ';'
  151. X        19. Number of functions
  152. X
  153. X        20. Average innermost block length (in semicolons)
  154. X        21. Standard deviation of the above
  155. X        22. Maximum innermost block length (in semicolons)
  156. X
  157. X        23. Average average block nesting depth per function
  158. X        24. Standard deviation of the above
  159. X        25. Maximum average block nesting depth per function
  160. X
  161. X
  162. X
  163. XII. FUNCTION REPORT
  164. X--------------------
  165. X
  166. X    Usage:  stattyF  report-filename  [ + exclude-files - ]  input-files
  167. X
  168. X    See I. for the handling of 'exclude-files'!
  169. X
  170. X    The following function attributes are considered:
  171. X
  172. X         1. Length (in bytes) ~
  173. X         2. Length (in lines) ~
  174. X         3. Average line length (in bytes) ~
  175. X
  176. X         4. Comments (in bytes) ~
  177. X         5. Portion of comment (in percent) ~
  178. X
  179. X         6. Number of 'if' statements
  180. X         7. Number of 'while' or 'do' statements
  181. X         8. Number of 'for' statements
  182. X         9. Number of 'switch' statements
  183. X        10. Number of 'goto' statements
  184. X        11. Number of labels
  185. X
  186. X        12. Number of ';'
  187. X        13. Number of all blocks
  188. X
  189. X        14. Average innermost block length (in semicolons)
  190. X        15. Standard deviation of the above
  191. X        16. Maximum innermost block length in (in semicolons)
  192. X
  193. X        17. Average block nesting depth
  194. X        18. Standard deviation of the above
  195. X        19. Maximum block nesting depth
  196. X
  197. X
  198. X
  199. XIII. CONTROL STRUCTURES & EXPRESSION REPORT
  200. X---------------------------------------------
  201. X
  202. X    Usage:  stattyCSE  report-filename  input-files
  203. X
  204. X    The following attributes are considered:
  205. X
  206. X          'if' statement:
  207. X         1. Length total (in lines)
  208. X         2. Number of ';' total
  209. X         3. Length of 'then' part (in lines)
  210. X         4. Number of ';' in 'then' part
  211. X         5. Length of 'else' part (in lines)
  212. X         6. Number of ';' in 'else' part
  213. X         7. Nesting depth
  214. X         8. Number of operators in 'if' condition
  215. X
  216. X        'while' or 'do' statement:
  217. X         9. Length total (in lines)
  218. X        10. Number of ';'
  219. X        11. Number of 'break' or 'continue' statements 
  220. X              regarding this 'do' or 'while'
  221. X        12. Nesting depth
  222. X        13. Number of operators in 'while' condition
  223. X
  224. X        'for' statement:
  225. X        14. Length total (in lines)
  226. X        15. Number of ';' (including those in head)
  227. X        16. Number of break statements regarding this 'for'
  228. X        17. Nesting depth
  229. X        18. Number of operators in second expression of head
  230. X
  231. X        'switch' statement:
  232. X        19. Length total (in lines)
  233. X        20. Number of ';'
  234. X        21. Number of case labels
  235. X        22. Number of break statements regarding this 'switch'
  236. X        23. Nesting depth
  237. X        24. Number of operators in head expression
  238. X
  239. X        expression statement (i.e. expression followed by ';'):
  240. X        25. Nesting depth
  241. X        26. Number of operators
  242. X
  243. X
  244. X
  245. XIV. BLOCK REPORT
  246. X-----------------
  247. X
  248. X    Usage:  stattyB  report-filename  input-files
  249. X
  250. X    The following attributes are considered:
  251. X
  252. X        blocks (no innermost blocks):
  253. X         1. Length (in lines)
  254. X         2. Number of ';'
  255. X         3. Nesting depth
  256. X         4. Total number of enclosed blocks
  257. X         5. Maximum absolute nesting depth of enclosed blocks
  258. X
  259. X        innermost blocks:
  260. X         6. Length (in lines)
  261. X         7. Number of ';'
  262. X         8. Nesting depth
  263. X
  264. X        all blocks (also innermost):
  265. X         9. Length (in lines)
  266. X        10. Number of ';'
  267. X        11. Nesting depth
  268. X
  269. X        innermost blocks & bodies of all blockless functions:
  270. X        12. Length (in lines)
  271. X        13. Number of ';'
  272. X        14. Nesting depth
  273. X
  274. X        all blocks (also innermost) & bodies of all functions:
  275. X        15. Length (in lines)
  276. X        16. Number of ';'
  277. X        17. Nesting depth
  278. X
  279. X
  280. X
  281. X
  282. X=============================================================================
  283. X3. How to use 'statty' program
  284. X=============================================================================
  285. X
  286. XUsage:  statty  [ -c ]  basename  [ + exclude-files - ]  input-files
  287. X
  288. X'statty' executes 'stattyM', 'stattyF', 'stattyCSE' and 'stattyB' one after 
  289. Xanother. The advantage of 'statty' is that the expansion of wildcard 
  290. Xexpressions in the command line is carried out only once. That's more effi-
  291. Xcient. If the -c option is used, 'statty' asks you to confirm before each 
  292. Xreport. If you answer in the negative the next report will be offered.
  293. XYou will find
  294. X
  295. X    the module report in 'basename.M',
  296. X    the function report in 'basename.F',
  297. X    the control structure & expression report in 'basename.CSE',
  298. X    the block report in 'basename.B'.
  299. X
  300. XSee 2.I for the handling of 'exclude-files'.
  301. X
  302. XTake care that the four tools are in the current working directory or in
  303. Xyour $PATH.
  304. X
  305. X=============================================================================
  306. END_OF_FILE
  307.   if test 8697 -ne `wc -c <'Ccount/README.2'`; then
  308.     echo shar: \"'Ccount/README.2'\" unpacked with wrong size!
  309.   fi
  310.   # end of 'Ccount/README.2'
  311. fi
  312. if test -f 'Ccount/statty' -a "${1}" != "-c" ; then 
  313.   echo shar: Will not clobber existing file \"'Ccount/statty'\"
  314. else
  315.   echo shar: Extracting \"'Ccount/statty'\" \(2188 characters\)
  316.   sed "s/^X//" >'Ccount/statty' <<'END_OF_FILE'
  317. X#!/tools/perl/bin/perl
  318. X
  319. X#############################################################################
  320. X#
  321. X#  Usage:  statty [ -c ] basename [ + exclude-files - ] input-files
  322. X#
  323. X#  'statty' reads data files in 'ccount' output format and give statistical 
  324. X#  reports about modules, functions, blocks, control structures and 
  325. X#  expressions of C source files.
  326. X#  It executes 'stattyM', 'stattyF', 'stattyCSE' and 'stattyB' one after
  327. X#  the other. If the -c option is used, 'statty' will ask you to confirm 
  328. X#  before each report. If you answer in the negative the next report will 
  329. X#  be offered.
  330. X#  The report filenames are 'basename.M', 'basename.F', 'basename.CSE' and
  331. X#  'basename.B'.
  332. X#  See 'README.1' and 'README.2' for more details!
  333. X#
  334. X#  Author: Joerg Lawrenz, Universitaet Karlsruhe
  335. X#  Date:   93/12/1
  336. X#
  337. X#############################################################################
  338. X
  339. X#
  340. X#  First get the -c option. 
  341. X#
  342. X
  343. Xif ($ARGV[0] eq "-c") {
  344. X   $switch = 1;
  345. X   shift;
  346. X   
  347. X }
  348. X
  349. X#
  350. X#  Exit if there are not enough arguments in the command line.
  351. X#
  352. X
  353. Xif (scalar(@ARGV) < 2) {
  354. X   print "Usage: statty [ -c ] basename [ + exclude-files - ] input-files\n";
  355. X   exit;
  356. X}
  357. X
  358. X#
  359. X#  Now get the basename for the single report names.
  360. X#
  361. X
  362. X$basename = shift;
  363. X
  364. X#
  365. X#  Now start the single report tools.
  366. X#
  367. X$reportname = $basename.".M";
  368. Xprint "Module report...\n";
  369. X`stattyM $reportname @ARGV` if &yes;
  370. X
  371. X$reportname = $basename.".F";
  372. Xprint "Function report...\n";
  373. X`stattyF $reportname @ARGV` if &yes;
  374. X
  375. X#
  376. X#  Now delete the exclude-files from the list.
  377. X#
  378. X
  379. Xif ($ARGV[0] eq '+') {
  380. X   shift;
  381. X   while ($ARGV[0] ne '-') {
  382. X      shift;
  383. X    }
  384. X   shift;
  385. X}
  386. X
  387. X$reportname = $basename.".CSE";
  388. Xprint "Control Structures & Expression report...\n";
  389. X`stattyCSE $reportname @ARGV` if &yes;
  390. X
  391. X$reportname = $basename.".B";
  392. Xprint "Block report...\n";
  393. X`stattyB $reportname @ARGV` if &yes;
  394. X
  395. X
  396. X#############################################################################
  397. X#
  398. X#  'yes' is the request subroutine.
  399. X#
  400. X#############################################################################
  401. X
  402. Xsub yes {
  403. X  if ($switch) {
  404. X    print STDOUT "Confirm (y/n): ";
  405. X    local($answer) = scalar(<STDIN>);
  406. X    $answer =~ /^y/i;
  407. X   }
  408. X  else {
  409. X    1;
  410. X  }
  411. X}
  412. END_OF_FILE
  413.   if test 2188 -ne `wc -c <'Ccount/statty'`; then
  414.     echo shar: \"'Ccount/statty'\" unpacked with wrong size!
  415.   fi
  416.   chmod +x 'Ccount/statty'
  417.   # end of 'Ccount/statty'
  418. fi
  419. if test -f 'Ccount/stattyB' -a "${1}" != "-c" ; then 
  420.   echo shar: Will not clobber existing file \"'Ccount/stattyB'\"
  421. else
  422.   echo shar: Extracting \"'Ccount/stattyB'\" \(7315 characters\)
  423.   sed "s/^X//" >'Ccount/stattyB' <<'END_OF_FILE'
  424. X#!/tools/perl/bin/perl
  425. X
  426. X#############################################################################
  427. X#
  428. X#  Usage:  stattyB  report-filename  input-files
  429. X#
  430. X#  'stattyB' reads data files in 'ccount' output format and gives a
  431. X#  statistical report about the structure of blocks in C source files.
  432. X#  See 'README.1' and 'README.2' for more details!
  433. X#
  434. X#  Author: Joerg Lawrenz, Universitaet Karlsruhe
  435. X#  Date:   93/12/1
  436. X#
  437. X#############################################################################
  438. X
  439. X#
  440. X#  First get the report-filename
  441. X#
  442. X
  443. X$file = shift;
  444. X
  445. X#
  446. X#  Exit if there are not enough arguments in the command line.
  447. X#
  448. X
  449. Xif (scalar(@ARGV) == 0) {
  450. X print STDERR "Usage: stattyB  report-filename  input-files\n";
  451. X exit;
  452. X}
  453. X
  454. X#
  455. X#  Get the names of the first and the last file for later report information.
  456. X#
  457. X
  458. X$FirstFile = $ARGV[0];
  459. X$LastFile = $ARGV[$#ARGV];
  460. X
  461. X#
  462. X#  Now read all input files line by line, count blocks, innermost blocks 
  463. X#  and functions, accumulates for their attribute field values the according 
  464. X#  histograms and count the modules. 
  465. X#  Consider attribute combinations of blocks, innermost blocks and function 
  466. X#  bodies:
  467. X#  $BI...  : all blocks + all innermost blocks
  468. X#  $FI...  : bodies of all blockless functions + innermost blocks
  469. X#  $BIF... : all blocks + innermost blocks + bodies of all functions
  470. X#
  471. X
  472. Xwhile (<>) {
  473. X  if (/^B/) {
  474. X    split;
  475. X    $BlockLines   {$_[1]}++;
  476. X    $BlockSemis   {$_[2]}++;
  477. X    $BlockDepth   {$_[3]}++;
  478. X    $BlockBlocks  {$_[4]}++;
  479. X    $BlockMaxDepth{$_[5]}++;
  480. X    $BIFLines{$_[1]}++;
  481. X    $BIFSemis{$_[2]}++;
  482. X    $BIFDepth{$_[3]}++;
  483. X    $BILines{$_[1]}++;
  484. X    $BISemis{$_[2]}++;
  485. X    $BIDepth{$_[3]}++;
  486. X    $blocks++;
  487. X    next;
  488. X   }
  489. X  if (/^F/) {
  490. X    split;
  491. X    $BIFLines{$_[2]}++;
  492. X    $BIFSemis{$_[4]}++;
  493. X    $BIFDepth{1}++;
  494. X    if ($_[11] == 0) {
  495. X      $FILines{$_[2]}++;
  496. X      $FISemis{$_[4]}++;
  497. X      $FIDepth{1}++;
  498. X      $NoBlockFunctions++;
  499. X     }
  500. X    $functions++;
  501. X    next;
  502. X   }
  503. X  if (/^I/) {
  504. X    split;
  505. X    $InBlockLines{$_[1]}++;
  506. X    $InBlockSemis{$_[2]}++;
  507. X    $InBlockDepth{$_[3]}++;
  508. X    $BIFLines{$_[1]}++;
  509. X    $BIFSemis{$_[2]}++;
  510. X    $BIFDepth{$_[3]}++;
  511. X    $BILines{$_[1]}++;
  512. X    $BISemis{$_[2]}++;
  513. X    $BIDepth{$_[3]}++;
  514. X    $FILines{$_[1]}++;
  515. X    $FISemis{$_[2]}++;
  516. X    $FIDepth{$_[3]}++;
  517. X    $inblocks++;
  518. X    next;
  519. X   }
  520. X  $module++ if /^M/;
  521. X}
  522. X
  523. X#
  524. X#  If no modules found, quit.
  525. X#
  526. X
  527. Xif (!$module) {
  528. X  print STDERR "No modules found!\n";
  529. X  exit;
  530. X}
  531. X
  532. X#
  533. X#  Now write the report by inserting for each attribute histogram
  534. X#  the statistical results of the subroutine 'stat'.
  535. X#
  536. X
  537. Xopen(FILE, "> $file");
  538. X
  539. Xchop($cwd = `pwd`);
  540. X
  541. Xprint  FILE "BLOCK REPORT  (from $cwd: $FirstFile ... $LastFile):\n\n";
  542. X
  543. Xprint  FILE "               Average Std.dev.  Max.    25q    [%]     50q    [%]     75q    [%]     90q    [%]     95q    [%]     98q    [%]     99q    [%]\n";
  544. Xprint  FILE "               ------- -------- ------ -------------- -------------- -------------- -------------- -------------- -------------- --------------";
  545. Xprint FILE "\n---- BLOCKS ----\n";
  546. X&printd('lines',          &stat(*BlockLines));
  547. X&printd('";"',            &stat(*BlockSemis));
  548. X&printd('depth',          &stat(*BlockDepth));
  549. X&printd('subblocks',      &stat(*BlockBlocks));
  550. X&printd('Max. depth/1',   &stat(*BlockMaxDepth));
  551. X
  552. Xprint FILE "\nINNERMOST BLOCKS\n";
  553. X&printd('lines',          &stat(*InBlockLines));
  554. X&printd('";"',            &stat(*InBlockSemis));
  555. X&printd('depth',          &stat(*InBlockDepth));
  556. X
  557. Xprint FILE "\n------ BI ------\n";
  558. X&printd('lines',          &stat(*BILines));
  559. X&printd('";"',            &stat(*BISemis));
  560. X&printd('depth',          &stat(*BIDepth));
  561. X
  562. Xprint FILE "\n-----  FI ------\n";
  563. X&printd('lines',     &stat(*FILines));
  564. X&printd('";"',       &stat(*FISemis));
  565. X&printd('depth',     &stat(*FIDepth));
  566. X
  567. Xprint FILE "\n----- BIF ------\n";
  568. X&printd('lines',     &stat(*BIFLines));
  569. X&printd('";"',       &stat(*BIFSemis));
  570. X&printd('depth',     &stat(*BIFDepth));
  571. X
  572. Xprintf FILE "\n\n# Modules:                %6d\n", $module;
  573. Xprintf FILE "# Functions:              %6d\n", $functions;
  574. Xprintf FILE "# Blocks (not innermost): %6d\n", $blocks;
  575. Xprintf FILE "# Innermost blocks:       %6d\n", $inblocks;
  576. Xprintf FILE "# Blockless functions:    %6d\n\n", $NoBlockFunctions;
  577. X
  578. Xprint FILE "BI  := all blocks + all innermost blocks\n";
  579. Xprint FILE "FI  := bodies of all blockless functions + innermost blocks\n";
  580. Xprint FILE "BIF := all blocks + innermost blocks + bodies of all functions\n";
  581. X
  582. Xprint FILE "\n/1  Maximum of all subblock nesting depths\n";
  583. X
  584. Xclose(FILE);
  585. X
  586. X
  587. X#############################################################################
  588. X#
  589. X#  Here is the subroutine 'stat', which calculates statistical values from
  590. X#  a given histogram.
  591. X#
  592. X#############################################################################
  593. X
  594. Xsub stat {
  595. X  local(*Array) = @_;
  596. X  local($i, $val, $sum, $num, $Average, $StdDev, $Max);
  597. X  local(@Quantil_25, @Quantil_50, @Quantil_75);
  598. X  local(@Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  599. X
  600. X#  Average:
  601. X
  602. X  while (($i,$val) = each %Array) {
  603. X    $sum += $val * $i;
  604. X    $num += $val;
  605. X    $Max = $i > $Max ? $i : $Max;
  606. X   }
  607. X  $Average = $num > 0 ? $sum/$num : 0;
  608. X
  609. X#  Standard deviation:
  610. X
  611. X  $sum = 0;
  612. X  while (($i,$val) = each %Array) {
  613. X    $sum += $val * ($i - $Average)**2;
  614. X   }
  615. X  $StdDev = $num > 1 ? sqrt($sum/($num-1)) : 0;
  616. X
  617. X# Quantils:
  618. X
  619. X  $sum = 0;
  620. X  foreach $i (sort numerically keys %Array) {
  621. X    $sum += 100 * $Array{$i} / $num;
  622. X
  623. X    if ($sum >= 25 && !defined @Quantil_25) {
  624. X      @Quantil_25 = ($i,$sum);
  625. X     }
  626. X    if ($sum >= 50 && !defined @Quantil_50) {
  627. X      @Quantil_50 = ($i,$sum);
  628. X     }
  629. X    if ($sum >= 75 && !defined @Quantil_75) {
  630. X      @Quantil_75 = ($i,$sum);
  631. X     }
  632. X    if ($sum >= 90 && !defined @Quantil_90) {
  633. X      @Quantil_90 = ($i,$sum);
  634. X     }
  635. X    if ($sum >= 95 && !defined @Quantil_95) {
  636. X      @Quantil_95 = ($i,$sum);
  637. X     }
  638. X    if ($sum >= 98 && !defined @Quantil_98) {
  639. X      @Quantil_98 = ($i,$sum);
  640. X     }
  641. X    if ($sum >= 99) {
  642. X      @Quantil_99 = ($i,$sum);
  643. X      last;
  644. X     }
  645. X   }
  646. X
  647. X#  Now return all results.
  648. X
  649. X  ($Average, $StdDev, $Max, @Quantil_25, @Quantil_50, @Quantil_75,
  650. X   @Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  651. X}
  652. X
  653. X
  654. X#############################################################################
  655. X#
  656. X#  'printd' is the right output subroutine for the combination of decimal
  657. X#  and floating point values.
  658. X#
  659. X#############################################################################
  660. X
  661. Xsub printd {
  662. X   local($object,@list) = @_;
  663. X
  664. X   printf FILE "%-15s%7.1f  %7.1f %6d %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f)\n",
  665. X                $object, @list;
  666. X}
  667. X
  668. X
  669. X#############################################################################
  670. X#
  671. X#  'printp' is the right output subroutine for floating point values only.
  672. X#
  673. X#############################################################################
  674. X
  675. Xsub printp {
  676. X   local($object,@list) = @_;
  677. X
  678. X   printf FILE "%-15s%7.1f  %7.1f %6.1f %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f)\n", $object, @list;
  679. X}
  680. X
  681. X
  682. X#############################################################################
  683. X#
  684. X#  This subroutine compares two values. It is used by a sorting routine
  685. X#  in 'stat'.
  686. X#
  687. X#############################################################################
  688. X
  689. Xsub numerically { $a <=> $b; }
  690. END_OF_FILE
  691.   if test 7315 -ne `wc -c <'Ccount/stattyB'`; then
  692.     echo shar: \"'Ccount/stattyB'\" unpacked with wrong size!
  693.   fi
  694.   chmod +x 'Ccount/stattyB'
  695.   # end of 'Ccount/stattyB'
  696. fi
  697. if test -f 'Ccount/stattyCSE' -a "${1}" != "-c" ; then 
  698.   echo shar: Will not clobber existing file \"'Ccount/stattyCSE'\"
  699. else
  700.   echo shar: Extracting \"'Ccount/stattyCSE'\" \(7466 characters\)
  701.   sed "s/^X//" >'Ccount/stattyCSE' <<'END_OF_FILE'
  702. X#!/tools/perl/bin/perl
  703. X
  704. X#############################################################################
  705. X#
  706. X#  Usage:  stattyCSE  report-filename  input-files
  707. X#
  708. X#  'stattyCSE' reads data files in 'ccount' output format and gives a
  709. X#  statistical report about control structures and expression of C 
  710. X#  source files.
  711. X#  See 'README.1' and 'README.2' for more details!
  712. X#
  713. X#  Author: Joerg Lawrenz, Universitaet Karlsruhe
  714. X#  Date:   93/12/1
  715. X#
  716. X#############################################################################
  717. X
  718. X#
  719. X#  First get the report-filename
  720. X#
  721. X
  722. X$file = shift;
  723. X
  724. X#
  725. X#  Exit if there are not enough arguments in the command line.
  726. X#
  727. X
  728. Xif (scalar(@ARGV) == 0) {
  729. X print STDERR "Usage: stattyCSE  report-filename  input-files\n";
  730. X exit;
  731. X}
  732. X
  733. X#
  734. X#  Get the names of the first and the last file for later report information.
  735. X#
  736. X
  737. X$FirstFile = $ARGV[0];
  738. X$LastFile = $ARGV[$#ARGV];
  739. X
  740. X#
  741. X#  Now read all input files line by line, count the objects (expression, 
  742. X#  'for', 'if', 'switch', 'while'), accumulates for their attribute field 
  743. X#  values the according histograms and count the modules.
  744. X#
  745. X
  746. Xwhile (<>) {
  747. X  if (/^e/) {
  748. X    split;
  749. X    $ExprOps  {$_[1]}++;
  750. X    $ExprDepth{$_[2]}++;
  751. X    $expr++;
  752. X    next;
  753. X   }
  754. X  if (/^f/) {
  755. X    split;
  756. X    $ForLines    {$_[1]}++;
  757. X    $ForSemis    {$_[2]}++;
  758. X    $ForDepth    {$_[3]}++;
  759. X    $ForOps      {$_[4]}++;
  760. X    $ForBreakCont{$_[5]}++;
  761. X    $for++;
  762. X    next;
  763. X   }
  764. X  if (/^i/) {
  765. X    split;
  766. X    $IfLines      {$_[1]}++;
  767. X    $IfOps        {$_[2]}++;
  768. X    $IfSemis{$_[4]+$_[6]}++;
  769. X    $IfPartLines  {$_[3]}++;
  770. X    $IfPartSemis  {$_[4]}++;
  771. X    $ElsePartLines{$_[5]}++;
  772. X    $ElsePartSemis{$_[6]}++;
  773. X    $IfDepth      {$_[7]}++;
  774. X    $if++;
  775. X    next;
  776. X   }
  777. X  if (/^s/) {
  778. X    split;
  779. X    $SwitchLines{$_[1]}++;
  780. X    $SwitchSemis{$_[2]}++;
  781. X    $SwitchDepth{$_[3]}++;
  782. X    $SwitchOps  {$_[4]}++;
  783. X    $SwitchCase {$_[5]}++;
  784. X    $SwitchBreak{$_[6]}++;
  785. X    $switch++;
  786. X    next;
  787. X   }
  788. X  if (/^w/) {
  789. X    split;
  790. X    $WhileLines    {$_[1]}++;
  791. X    $WhileSemis    {$_[2]}++;
  792. X    $WhileDepth    {$_[3]}++;
  793. X    $WhileOps      {$_[4]}++;
  794. X    $WhileBreakCont{$_[5]}++;
  795. X    $while++;
  796. X    next;
  797. X   }
  798. X  $module++ if /^M/;
  799. X}
  800. X
  801. X#
  802. X#  If no modules found, quit.
  803. X#
  804. X
  805. Xif (!$module) {
  806. X  print STDERR "No modules found!\n";
  807. X  exit;
  808. X}
  809. X
  810. X#
  811. X#  Now write the report by inserting for each attribute histogram 
  812. X#  the statistical results of the subroutine 'stat'.
  813. X#
  814. X
  815. Xopen(FILE, "> $file");
  816. X
  817. Xchop($cwd = `pwd`);
  818. X
  819. Xprint  FILE "CONTROL STRUCTURES & EXPRESSION REPORT  (from $cwd: $FirstFile ... $LastFile):\n\n";
  820. X
  821. Xprint  FILE "               Average Std.dev.  Max.    25q    [%]     50q    [%]     75q    [%]     90q    [%]     95q    [%]     98q    [%]     99q    [%]\n";
  822. Xprint  FILE "               ------- -------- ------ -------------- -------------- -------------- -------------- -------------- -------------- --------------";
  823. Xprint FILE "\n----- IF -----\n";
  824. X&printd('lines',          &stat(*IfLines));
  825. X&printd('";"',            &stat(*IfSemis));
  826. X&printd('lines if-part',  &stat(*IfPartLines));
  827. X&printd('";" if-part',    &stat(*IfPartSemis));
  828. X&printd('lines else-part',&stat(*ElsePartLines));
  829. X&printd('";" else-part',  &stat(*ElsePartSemis));
  830. X&printd('depth',          &stat(*IfDepth));
  831. X&printd('operators/1',    &stat(*IfOps));
  832. X
  833. Xprint FILE "\n--- WHILE ----\n";
  834. X&printd('lines',          &stat(*WhileLines));
  835. X&printd('";"',            &stat(*WhileSemis));
  836. X&printd('"break","cont."',&stat(*WhileBreakCont));
  837. X&printd('depth',          &stat(*WhileDepth));
  838. X&printd('operators/1',    &stat(*WhileOps));
  839. X
  840. Xprint FILE "\n---- FOR -----\n";
  841. X&printd('lines',          &stat(*ForLines));
  842. X&printd('";"',            &stat(*ForSemis));
  843. X&printd('"break","cont."',&stat(*ForBreakCont));
  844. X&printd('depth',          &stat(*ForDepth));
  845. X&printd('operators/2',    &stat(*ForOps));
  846. X
  847. Xprint FILE "\n--- SWITCH ---\n";
  848. X&printd('lines',     &stat(*SwitchLines));
  849. X&printd('";"',       &stat(*SwitchSemis));
  850. X&printd('"case"',    &stat(*SwitchCase));
  851. X&printd('"break"',   &stat(*SwitchBreak));
  852. X&printd('depth',     &stat(*SwitchDepth));
  853. X&printd('operators/3',&stat(*SwitchOps));
  854. X
  855. Xprint FILE "\n- EXPRESSION/4 -\n";
  856. X&printd('depth',     &stat(*ExprDepth));
  857. X&printd('operators', &stat(*ExprOps));
  858. X
  859. Xprintf FILE "\n\n# Modules:     %6d\n", $module;
  860. Xprintf FILE "# If:          %6d\n", $if;
  861. Xprintf FILE "# While:       %6d\n", $while;
  862. Xprintf FILE "# For:         %6d\n", $for;
  863. Xprintf FILE "# Switch:      %6d\n", $switch;
  864. Xprintf FILE "# Expressions: %6d\n", $expr;
  865. X
  866. Xprint FILE "\n/1  operators in head condition";
  867. Xprint FILE "\n/2  operators in second expression of head";
  868. Xprint FILE "\n/3  operators in head expression\n";
  869. Xprint FILE "\n/4  statement followed by ';'";
  870. X
  871. Xclose(FILE);
  872. X
  873. X
  874. X#############################################################################
  875. X#
  876. X#  Here is the subroutine 'stat', which calculates statistical values from 
  877. X#  a given histogram.
  878. X#
  879. X#############################################################################
  880. X
  881. Xsub stat {
  882. X  local(*Array) = @_;
  883. X  local($i, $val, $sum, $num, $Average, $StdDev, $Max);
  884. X  local(@Quantil_25, @Quantil_50, @Quantil_75);
  885. X  local(@Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  886. X
  887. X#  Average:
  888. X
  889. X  while (($i,$val) = each %Array) {
  890. X    $sum += $val * $i;
  891. X    $num += $val;
  892. X    $Max = $i > $Max ? $i : $Max;
  893. X   }
  894. X  $Average = $num > 0 ? $sum/$num : 0;
  895. X
  896. X#  Standard deviation:
  897. X
  898. X  $sum = 0;
  899. X  while (($i,$val) = each %Array) {
  900. X    $sum += $val * ($i - $Average)**2;
  901. X   }
  902. X  $StdDev = $num > 1 ? sqrt($sum/($num-1)) : 0;
  903. X
  904. X#  Quantils:
  905. X
  906. X  $sum = 0;
  907. X  foreach $i (sort numerically keys %Array) {
  908. X    $sum += 100 * $Array{$i} / $num;
  909. X
  910. X    if ($sum >= 25 && !defined @Quantil_25) {
  911. X      @Quantil_25 = ($i,$sum);
  912. X     }
  913. X    if ($sum >= 50 && !defined @Quantil_50) {
  914. X      @Quantil_50 = ($i,$sum);
  915. X     }
  916. X    if ($sum >= 75 && !defined @Quantil_75) {
  917. X      @Quantil_75 = ($i,$sum);
  918. X     }
  919. X    if ($sum >= 90 && !defined @Quantil_90) {
  920. X      @Quantil_90 = ($i,$sum);
  921. X     }
  922. X    if ($sum >= 95 && !defined @Quantil_95) {
  923. X      @Quantil_95 = ($i,$sum);
  924. X     }
  925. X    if ($sum >= 98 && !defined @Quantil_98) {
  926. X      @Quantil_98 = ($i,$sum);
  927. X     }
  928. X    if ($sum >= 99) {
  929. X      @Quantil_99 = ($i,$sum);
  930. X      last;
  931. X     }
  932. X   }
  933. X
  934. X#  Now return all results.
  935. X
  936. X  ($Average, $StdDev, $Max, @Quantil_25, @Quantil_50, @Quantil_75,
  937. X   @Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  938. X}
  939. X
  940. X
  941. X#############################################################################
  942. X#
  943. X#  'printd' is the right output subroutine for the combination of decimal 
  944. X#  and floating point values.
  945. X#
  946. X#############################################################################
  947. X
  948. Xsub printd {
  949. X   local($object,@list) = @_;
  950. X
  951. X   printf FILE "%-15s%7.1f  %7.1f %6d %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f)\n",
  952. X                $object, @list;
  953. X}
  954. X
  955. X
  956. X#############################################################################
  957. X#
  958. X#  'printp' is the right output subroutine for floating point values only.
  959. X#
  960. X#############################################################################
  961. X
  962. Xsub printp {
  963. X   local($object,@list) = @_;
  964. X
  965. X   printf FILE "%-15s%7.1f  %7.1f %6.1f %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f)\n", $object, @list;
  966. X}
  967. X
  968. X
  969. X#############################################################################
  970. X#
  971. X#  This subroutine compares two values. It is used by a sorting routine 
  972. X#  in 'stat'.
  973. X#
  974. X#############################################################################
  975. X
  976. Xsub numerically { $a <=> $b; }
  977. END_OF_FILE
  978.   if test 7466 -ne `wc -c <'Ccount/stattyCSE'`; then
  979.     echo shar: \"'Ccount/stattyCSE'\" unpacked with wrong size!
  980.   fi
  981.   chmod +x 'Ccount/stattyCSE'
  982.   # end of 'Ccount/stattyCSE'
  983. fi
  984. if test -f 'Ccount/stattyF' -a "${1}" != "-c" ; then 
  985.   echo shar: Will not clobber existing file \"'Ccount/stattyF'\"
  986. else
  987.   echo shar: Extracting \"'Ccount/stattyF'\" \(7152 characters\)
  988.   sed "s/^X//" >'Ccount/stattyF' <<'END_OF_FILE'
  989. X#!/tools/perl/bin/perl
  990. X
  991. X#############################################################################
  992. X#
  993. X#  Usage:  stattyF  report-filename  [ + exclude-files - ]  input-files
  994. X#
  995. X#  'stattyF' reads data files in 'ccount' output format and gives a
  996. X#  statistical report about the structure of functions in C source files.
  997. X#  See 'README.1' and 'README.2' for more details!
  998. X#
  999. X#  Author: Joerg Lawrenz, Universitaet Karlsruhe
  1000. X#  Date:   93/12/1
  1001. X#
  1002. X#############################################################################
  1003. X
  1004. X#
  1005. X#  First get the report-filename
  1006. X#
  1007. X
  1008. X$file = shift;
  1009. X
  1010. X#
  1011. X#  Now save the names of the exclude-files and count them.
  1012. X#
  1013. X
  1014. Xif ($ARGV[0] eq '+') {
  1015. X   shift;
  1016. X   $FirstExcludeFile = $ARGV[0];
  1017. X   while ($ARGV[0] ne '-') {
  1018. X      $filename = shift;
  1019. X      $EXclude{$filename}++;
  1020. X      $Mexclude++;
  1021. X      if (scalar(@ARGV) == 0) {
  1022. X         print STDERR "Usage: stattyF  report-filename  [ + exclude-files - ]  input-files\n";
  1023. X         exit;
  1024. X       }
  1025. X    }
  1026. X   shift;
  1027. X   $LastExcludeFile = $filename;
  1028. X}
  1029. X
  1030. X#
  1031. X#  Exit if there are not enough arguments in the command line.
  1032. X#
  1033. X
  1034. Xif (scalar(@ARGV) == 0) {
  1035. X print STDERR "Usage: stattyF  report-filename  [ + exclude-files - ]  input-files\n";
  1036. X exit;
  1037. X}
  1038. X
  1039. X#
  1040. X#  Get the names of the first and the last file for later report information.
  1041. X#
  1042. X
  1043. X$FirstFile = $ARGV[0];
  1044. X$LastFile = $ARGV[$#ARGV];
  1045. X
  1046. X#
  1047. X#  Now read all input files line by line, accumulates for the function 
  1048. X#  attribute field values and for calculations from them the according 
  1049. X#  histograms, and count the functions and the modules.
  1050. X#
  1051. X
  1052. Xwhile (<>) {
  1053. X  if (/^F/) {
  1054. X    split;
  1055. X
  1056. X#  For the first 5 attributes, accumulate the histograms only if the
  1057. X#  current function results are not in a exclude-file.
  1058. X
  1059. X    if (!$EXclude{$ARGV}) {
  1060. X        $BYTES{$_[1]}++;
  1061. X        $LINES{$_[2]}++;
  1062. X        $ByteLineQuotient { sprintf("%.1f", $_[1]/$_[2]) } ++;
  1063. X        $Comment{$_[3]}++;
  1064. X        $CommentPortion { sprintf("%.1f", 100*$_[3]/$_[1]) } ++;
  1065. X       } 
  1066. X     else {
  1067. X        $Fexclude++;
  1068. X       }
  1069. X    $SEMIS {$_[4]}++;
  1070. X    $IF    {$_[5]}++;
  1071. X    $WHILE {$_[6]}++;
  1072. X    $FOR   {$_[7]}++;
  1073. X    $SWITCH{$_[8]}++;
  1074. X    $GOTO  {$_[9]}++;
  1075. X    $LABEL {$_[10]}++;
  1076. X    $BLOCKS{$_[11]}++;
  1077. X    $AveInblockLen{$_[12]}++;
  1078. X    $DevInblockLen{$_[13]}++;
  1079. X    $MaxInblockLen{$_[14]}++;
  1080. X    $AveDepth{$_[15]}++;
  1081. X    $DevDepth{$_[16]}++;
  1082. X    $MaxDepth{$_[17]}++;
  1083. X    $functions++;
  1084. X   }
  1085. X   $module++ if /^M/;
  1086. X}
  1087. X
  1088. X#
  1089. X#  If no functions found, quit.
  1090. X#
  1091. X
  1092. Xif (!$functions) {
  1093. X  print STDERR "No functions found!\n";
  1094. X  exit;
  1095. X}
  1096. X
  1097. X#
  1098. X#  Now write the report by inserting for each attribute histogram
  1099. X#  the statistical results of the subroutine 'stat'.
  1100. X#
  1101. X
  1102. Xopen(FILE, "> $file");
  1103. X
  1104. Xchop($cwd = `pwd`);
  1105. X
  1106. Xprint  FILE "FUNCTION REPORT  (from $cwd: $FirstFile ... $LastFile, excluded(~): $FirstExcludeFile ... $LastExcludeFile):\n\n";
  1107. X
  1108. Xprint  FILE "              Average Std.dev.  Max.    25q    [%]     50q    [%]     75q    [%]     90q    [%]     95q    [%]     98q    [%]     99q    [%]\n";
  1109. Xprint  FILE "              ------- -------- ------ -------------- -------------- -------------- -------------- -------------- -------------- --------------\n";
  1110. X&printd('bytes~',        &stat(*BYTES));
  1111. X&printd('lines~',        &stat(*LINES));
  1112. X&printp('bytes/line~',   &stat(*ByteLineQuotient));
  1113. X
  1114. Xprint FILE "\nComment~:\n";
  1115. X&printd('bytes',         &stat(*Comment));
  1116. X&printp('portion',       &stat(*CommentPortion));
  1117. X
  1118. Xprint FILE "\n";
  1119. X&printd('if',            &stat(*IF));
  1120. X&printd('while',         &stat(*WHILE));
  1121. X&printd('for',           &stat(*FOR));
  1122. X&printd('switch',        &stat(*SWITCH));
  1123. X&printd('goto',          &stat(*GOTO));
  1124. X&printd('label',         &stat(*LABEL));
  1125. X
  1126. Xprint FILE "\n";
  1127. X&printd('";"',           &stat(*SEMIS));
  1128. X&printd('blocks',        &stat(*BLOCKS));
  1129. X
  1130. Xprint FILE "\nInnermost block length in ';' (*):\n";
  1131. X&printp('Average', &stat(*AveInblockLen));
  1132. X&printp('Std.dev.',&stat(*DevInblockLen));
  1133. X&printd('Maximum', &stat(*MaxInblockLen));
  1134. X
  1135. Xprint FILE "\nBlock nesting depth:\n";
  1136. X&printp('Average', &stat(*AveDepth));
  1137. X&printp('Std.dev.',&stat(*DevDepth));
  1138. X&printd('Maximum', &stat(*MaxDepth));
  1139. X
  1140. Xprint FILE "\n\nModules:   $module\n";
  1141. Xprint FILE "Functions: $functions\n\n";
  1142. Xprintf FILE "~ Excluded:  %d functions in %d modules\n", 
  1143. X                             $Fexclude, $Mexclude;
  1144. Xprint FILE "\n";
  1145. Xprint FILE "(*) + blockless functions\n";
  1146. Xclose(FILE);
  1147. X
  1148. X
  1149. X#############################################################################
  1150. X#
  1151. X#  Here is the subroutine 'stat', which calculates statistical values from
  1152. X#  a given histogram.
  1153. X#
  1154. X#############################################################################
  1155. X
  1156. Xsub stat {
  1157. X  local(*Array) = @_;
  1158. X  local($i, $val, $sum, $num, $Average, $StdDev, $Max);
  1159. X  local(@Quantil_25, @Quantil_50, @Quantil_75);
  1160. X  local(@Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  1161. X
  1162. X#  Average:
  1163. X
  1164. X  while (($i,$val) = each %Array) {
  1165. X    $sum += $val * $i;
  1166. X    $num += $val;
  1167. X    $Max = $i > $Max ? $i : $Max;
  1168. X   }
  1169. X  $Average = $num > 0 ? $sum/$num : 0;
  1170. X
  1171. X#  Standard Deviation:
  1172. X
  1173. X  $sum = 0;
  1174. X  while (($i,$val) = each %Array) {
  1175. X    $sum += $val * ($i - $Average)**2;
  1176. X   }
  1177. X  $StdDev = $num > 1 ? sqrt($sum/($num-1)) : 0;
  1178. X
  1179. X#  Quantils:
  1180. X
  1181. X  $sum = 0;
  1182. X  foreach $i (sort numerically keys %Array) {
  1183. X    $sum += 100 * $Array{$i} / $num;
  1184. X
  1185. X    if ($sum >= 25 && !defined @Quantil_25) {
  1186. X      @Quantil_25 = ($i,$sum);
  1187. X     }
  1188. X    if ($sum >= 50 && !defined @Quantil_50) {
  1189. X      @Quantil_50 = ($i,$sum);
  1190. X     }
  1191. X    if ($sum >= 75 && !defined @Quantil_75) {
  1192. X      @Quantil_75 = ($i,$sum);
  1193. X     }
  1194. X    if ($sum >= 90 && !defined @Quantil_90) {
  1195. X      @Quantil_90 = ($i,$sum);
  1196. X     }
  1197. X    if ($sum >= 95 && !defined @Quantil_95) {
  1198. X      @Quantil_95 = ($i,$sum);
  1199. X     }
  1200. X    if ($sum >= 98 && !defined @Quantil_98) {
  1201. X      @Quantil_98 = ($i,$sum);
  1202. X     }
  1203. X    if ($sum >= 99) {
  1204. X      @Quantil_99 = ($i,$sum);
  1205. X      last;
  1206. X     }
  1207. X   }
  1208. X
  1209. X# Now return all results.
  1210. X
  1211. X  ($Average, $StdDev, $Max, @Quantil_25, @Quantil_50, @Quantil_75,
  1212. X   @Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  1213. X}
  1214. X
  1215. X
  1216. X#############################################################################
  1217. X#
  1218. X#  'printd' is the right output subroutine for the combination of decimal
  1219. X#  and floating point values.
  1220. X#
  1221. X#############################################################################
  1222. X
  1223. Xsub printd {
  1224. X   local($object,@list) = @_;
  1225. X
  1226. X   printf FILE "%-14s %6.1f   %6.1f %6d %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f)\n",
  1227. X                $object, @list;
  1228. X}
  1229. X
  1230. X
  1231. X#############################################################################
  1232. X#
  1233. X#  'printp' is the right output subroutine for floating point values only.
  1234. X#
  1235. X#############################################################################
  1236. X
  1237. Xsub printp {
  1238. X   local($object,@list) = @_;
  1239. X
  1240. X   printf FILE "%-14s %6.1f   %6.1f %6.1f %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f)\n", $object, @list;
  1241. X}
  1242. X
  1243. X
  1244. X#############################################################################
  1245. X#
  1246. X#  This subroutine compares two values. It is used by a sorting routine
  1247. X#  in 'stat'.
  1248. X#
  1249. X#############################################################################
  1250. X
  1251. Xsub numerically { $a <=> $b; }
  1252. END_OF_FILE
  1253.   if test 7152 -ne `wc -c <'Ccount/stattyF'`; then
  1254.     echo shar: \"'Ccount/stattyF'\" unpacked with wrong size!
  1255.   fi
  1256.   chmod +x 'Ccount/stattyF'
  1257.   # end of 'Ccount/stattyF'
  1258. fi
  1259. if test -f 'Ccount/stattyM' -a "${1}" != "-c" ; then 
  1260.   echo shar: Will not clobber existing file \"'Ccount/stattyM'\"
  1261. else
  1262.   echo shar: Extracting \"'Ccount/stattyM'\" \(7905 characters\)
  1263.   sed "s/^X//" >'Ccount/stattyM' <<'END_OF_FILE'
  1264. X#!/tools/perl/bin/perl
  1265. X
  1266. X#############################################################################
  1267. X#
  1268. X#  Usage:  stattyM  report-filename  [ + exclude-files - ]  input-files
  1269. X#
  1270. X#  'stattyM' reads data files in 'ccount' output format and gives a
  1271. X#  statistical report about the structure of modules in C source files
  1272. X#  (only global results are considered here).
  1273. X#  See 'README.1' and 'README.2' for more details!
  1274. X#
  1275. X#  Author: Joerg Lawrenz, Universitaet Karlsruhe
  1276. X#  Date:   93/12/1
  1277. X#
  1278. X#############################################################################
  1279. X
  1280. X#
  1281. X#  First get the report-filename
  1282. X#
  1283. X
  1284. X$file = shift;
  1285. X
  1286. X#
  1287. X#  Now save the names of the exclude-files and count them.
  1288. X#
  1289. X
  1290. Xif ($ARGV[0] eq '+') {
  1291. X   shift;
  1292. X   $FirstExcludeFile = $ARGV[0];
  1293. X   while ($ARGV[0] ne '-') {
  1294. X      $filename = shift;
  1295. X      $EXclude{$filename}++;
  1296. X      $Mexclude++;
  1297. X      if (scalar(@ARGV) == 0) {
  1298. X         print STDERR "Usage: stattyM  report-filename  [ + exclude-files - ]  input-files\n";
  1299. X         exit;
  1300. X       }
  1301. X    }
  1302. X   shift;
  1303. X   $LastExcludeFile = $filename;
  1304. X}
  1305. X
  1306. X#
  1307. X# Exit if there are not enough arguments in the command line.
  1308. X#
  1309. X
  1310. Xif (scalar(@ARGV) == 0) {
  1311. X print STDERR "Usage: stattyM  report-filename  [ + exclude-files - ]  input-files\n";
  1312. X exit;
  1313. X}
  1314. X
  1315. X#
  1316. X#  Get the names of the first and the last file for later report information.
  1317. X#
  1318. X
  1319. X$FirstFile = $ARGV[0];
  1320. X$LastFile = $ARGV[$#ARGV];
  1321. X
  1322. X#
  1323. X#  Now read all input files line by line, accumulates for the module
  1324. X#  attribute field values and for calculations from them the according
  1325. X#  histograms, and count the modules.
  1326. X#
  1327. X
  1328. Xwhile (<>) {
  1329. X  if (/^M/) {
  1330. X    split;
  1331. X
  1332. X#  For the first 12 attributes, accumulate the histograms only if the
  1333. X#  current module results are not in a exclude-file.
  1334. X
  1335. X    if (!$EXclude{$ARGV}) {
  1336. X        $BYTES  {$_[1]}++;
  1337. X        $LINES  {$_[2]}++;
  1338. X        $ByteLineQuotient { sprintf("%.1f", $_[2] ? $_[1]/$_[2] : 0) } ++;
  1339. X        $Comment{$_[3]}++;
  1340. X        $PPcomment{$_[4]}++;
  1341. X        $relevBytes = $_[6]+$_[8]+$_[10];
  1342. X        $RelevBytes{$relevBytes}++;
  1343. X        $BLANKS{ $_[1]-$_[3]-$_[4]-$relevBytes }++;
  1344. X
  1345. X        $CommentPortion  { sprintf("%.1f", 100*$_[3]/$_[1]) } ++;
  1346. X        $PPCommentPortion{ sprintf("%.1f", 100*$_[4]/$_[1]) } ++;
  1347. X        $RelevBytePortion{ sprintf("%.1f", 100*$relevBytes/$_[1]) } ++;
  1348. X        $BlankPortion    { sprintf("%.1f", 
  1349. X                  100 * (1 - ($_[3]+$_[4]+$relevBytes)/$_[1]) ) } ++;
  1350. X        
  1351. X       } 
  1352. X    $NumId    {$_[5]}++;
  1353. X    $ByteId   {$_[6]}++;
  1354. X    $NumSym   {$_[7]}++;
  1355. X    $ByteSym  {$_[8]}++;
  1356. X    $NumPP    {$_[9]}++;
  1357. X    $BytePP   {$_[10]}++;
  1358. X    $Semi     {$_[11]}++;
  1359. X    $Functions{$_[12]}++;
  1360. X    $AveInblockLen{$_[13]}++;
  1361. X    $DevInblockLen{$_[14]}++;
  1362. X    $MaxInblockLen{$_[15]}++;
  1363. X    $AveAveDepth{$_[16]}++;
  1364. X    $DevAveDepth{$_[17]}++;
  1365. X    $MaxAveDepth{$_[18]}++;
  1366. X    $module++;
  1367. X   }
  1368. X}
  1369. X
  1370. X#
  1371. X#  If no modules found, quit.
  1372. X#
  1373. X
  1374. Xif (!$module) {
  1375. X  print STDERR "No modules found!\n";
  1376. X  exit;
  1377. X}
  1378. X
  1379. X#
  1380. X#  Now write the report by inserting for each attribute histogram
  1381. X#  the statistical results of the subroutine 'stat'.
  1382. X#
  1383. X
  1384. Xopen(FILE, "> $file");
  1385. X
  1386. Xchop($cwd = `pwd`);
  1387. X
  1388. Xprint  FILE "MODULE REPORT  (from $cwd: $FirstFile ... $LastFile, excluded(~): $FirstExcludeFile ... $LastExcludeFile):\n\n";
  1389. X
  1390. Xprint  FILE "               Average Std.dev.  Max.    25q    [%]     50q    [%]     75q    [%]     90q    [%]     95q    [%]     98q    [%]     99q    [%]\n";
  1391. Xprint  FILE "               ------- -------- ------ -------------- -------------- -------------- -------------- -------------- -------------- --------------\n";
  1392. X&printd('bytes~',        &stat(*BYTES));
  1393. X&printd('lines~',        &stat(*LINES));
  1394. X&printp('bytes/line~',   &stat(*ByteLineQuotient));
  1395. X
  1396. Xprint FILE "\nBytes~:\n";
  1397. X&printd('Comment',       &stat(*Comment));
  1398. X&printd('PPcomment',     &stat(*PPcomment));
  1399. X&printd('Relev. symb.',  &stat(*RelevBytes));
  1400. X&printd('"Blanks"',      &stat(*BLANKS));
  1401. X
  1402. Xprint FILE "\nPortions[%]~:\n";
  1403. X&printp('Comment',       &stat(*CommentPortion));
  1404. X&printp('PPcomment',     &stat(*PPCommentPortion));
  1405. X&printp('Relev. symb.',  &stat(*RelevBytePortion));
  1406. X&printp('"Blanks"',      &stat(*BlankPortion));
  1407. X
  1408. Xprint FILE "\n";
  1409. X&printd('#identifier',   &stat(*NumId));
  1410. X&printd('bytes id',      &stat(*ByteId));
  1411. Xprint FILE "\n";
  1412. X&printd('#symbols',      &stat(*NumSym));
  1413. X&printd('bytes sym',     &stat(*ByteSym));
  1414. Xprint FILE "\n";
  1415. X&printd('#PP-directives',&stat(*NumPP));
  1416. X&printd('bytes PP-dir',  &stat(*BytePP));
  1417. X
  1418. Xprint FILE "\n";
  1419. X&printd('";"',           &stat(*Semi));
  1420. X&printd('functions',     &stat(*Functions));
  1421. X
  1422. Xprint FILE "\nInnermost block length in ';' (*):\n";
  1423. X&printp('Average',       &stat(*AveInblockLen));
  1424. X&printp('Std.dev.',      &stat(*DevInblockLen));
  1425. X&printd('Maximum',       &stat(*MaxInblockLen));
  1426. X
  1427. Xprint FILE "\nAverage block nesting depth per function:\n";
  1428. X&printp('Average',       &stat(*AveAveDepth));
  1429. X&printp('Std.dev',       &stat(*DevAveDepth));
  1430. X&printp('Maximum',       &stat(*MaxAveDepth));
  1431. X
  1432. Xprintf FILE "\n\nModules total:   %5d\n", $module;
  1433. Xprintf FILE "~ Excluded:      %5d\n", $Mexclude;
  1434. Xprint FILE "\n";
  1435. Xprint FILE "(*) + blockless functions\n";
  1436. Xclose(FILE);
  1437. X
  1438. X
  1439. X#############################################################################
  1440. X#
  1441. X#  Here is the subroutine 'stat', which calculates statistical values from
  1442. X#  a given histogram.
  1443. X#
  1444. X#############################################################################
  1445. X
  1446. Xsub stat {
  1447. X  local(*Array) = @_;
  1448. X  local($i, $val, $sum, $num, $Average, $StdDev, $Max);
  1449. X  local(@Quantil_25, @Quantil_50, @Quantil_75);
  1450. X  local(@Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  1451. X
  1452. X#  Average:
  1453. X
  1454. X  while (($i,$val) = each %Array) {
  1455. X    $sum += $val * $i;
  1456. X    $num += $val;
  1457. X    $Max = $i > $Max ? $i : $Max;
  1458. X   }
  1459. X  $Average = $num > 0 ? $sum/$num : 0;
  1460. X
  1461. X#  Standard Deviation:
  1462. X
  1463. X  $sum = 0;
  1464. X  while (($i,$val) = each %Array) {
  1465. X    $sum += $val * ($i - $Average)**2;
  1466. X   }
  1467. X  $StdDev = $num > 1 ? sqrt($sum/($num-1)) : 0;
  1468. X
  1469. X#  Quantils:
  1470. X
  1471. X  $sum = 0;
  1472. X  foreach $i (sort numerically keys %Array) {
  1473. X    $sum += 100 * $Array{$i} / $num;
  1474. X
  1475. X    if ($sum >= 25 && !defined @Quantil_25) {
  1476. X      @Quantil_25 = ($i,$sum);
  1477. X     }
  1478. X    if ($sum >= 50 && !defined @Quantil_50) {
  1479. X      @Quantil_50 = ($i,$sum);
  1480. X     }
  1481. X    if ($sum >= 75 && !defined @Quantil_75) {
  1482. X      @Quantil_75 = ($i,$sum);
  1483. X     }
  1484. X    if ($sum >= 90 && !defined @Quantil_90) {
  1485. X      @Quantil_90 = ($i,$sum);
  1486. X     }
  1487. X    if ($sum >= 95 && !defined @Quantil_95) {
  1488. X      @Quantil_95 = ($i,$sum);
  1489. X     }
  1490. X    if ($sum >= 98 && !defined @Quantil_98) {
  1491. X      @Quantil_98 = ($i,$sum);
  1492. X     }
  1493. X    if ($sum >= 99) {
  1494. X      @Quantil_99 = ($i,$sum);
  1495. X      last;
  1496. X     }
  1497. X   }
  1498. X
  1499. X# Now return all results.
  1500. X
  1501. X  ($Average, $StdDev, $Max, @Quantil_25, @Quantil_50, @Quantil_75,
  1502. X   @Quantil_90, @Quantil_95, @Quantil_98, @Quantil_99);
  1503. X}
  1504. X
  1505. X
  1506. X#############################################################################
  1507. X#
  1508. X#  'printd' is the right output subroutine for the combination of decimal
  1509. X#  and floating point values.
  1510. X#
  1511. X#############################################################################
  1512. X
  1513. Xsub printd {
  1514. X   local($object,@list) = @_;
  1515. X
  1516. X   printf FILE "%-15s%7.1f  %7.1f %6d %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f) %6d (%5.1f)\n",
  1517. X                $object, @list;
  1518. X}
  1519. X
  1520. X
  1521. X#############################################################################
  1522. X#
  1523. X#  'printp' is the right output subroutine for floating point values only.
  1524. X#
  1525. X#############################################################################
  1526. X
  1527. Xsub printp {
  1528. X   local($object,@list) = @_;
  1529. X
  1530. X   printf FILE "%-15s%7.1f  %7.1f %6.1f %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f) %6.1f (%5.1f)\n", $object, @list;
  1531. X}
  1532. X
  1533. X
  1534. X#############################################################################
  1535. X#
  1536. X#  This subroutine compares two values. It is used by a sorting routine
  1537. X#  in 'stat'.
  1538. X#
  1539. X#############################################################################
  1540. X
  1541. Xsub numerically { $a <=> $b; }
  1542. END_OF_FILE
  1543.   if test 7905 -ne `wc -c <'Ccount/stattyM'`; then
  1544.     echo shar: \"'Ccount/stattyM'\" unpacked with wrong size!
  1545.   fi
  1546.   chmod +x 'Ccount/stattyM'
  1547.   # end of 'Ccount/stattyM'
  1548. fi
  1549. echo shar: End of archive 3 \(of 3\).
  1550. cp /dev/null ark3isdone
  1551. MISSING=""
  1552. for I in 1 2 3 ; do
  1553.     if test ! -f ark${I}isdone ; then
  1554.     MISSING="${MISSING} ${I}"
  1555.     fi
  1556. done
  1557. if test "${MISSING}" = "" ; then
  1558.     echo You have unpacked all 3 archives.
  1559.     rm -f ark[1-9]isdone
  1560. else
  1561.     echo You still must unpack the following archives:
  1562.     echo "        " ${MISSING}
  1563. fi
  1564. exit 0
  1565. exit 0 # Just in case...
  1566.