home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume20 / metrics / part09 < prev    next >
Encoding:
Internet Message Format  |  1989-09-18  |  9.4 KB

  1. Subject:  v20i016:  Tools for generating software metrics, Part09/14
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Brian Renaud <!huron.ann-arbor.mi.us!bdr>
  7. Posting-number: Volume 20, Issue 16
  8. Archive-name: metrics/part09
  9.  
  10. ---- Cut Here and unpack ----
  11. #!/bin/sh
  12. # this is part 9 of a multipart archive
  13. # do not concatenate these parts, unpack them in order with /bin/sh
  14. # file src/kdsi/kdsi.c continued
  15. #
  16. CurArch=9
  17. if test ! -r s2_seq_.tmp
  18. then echo "Please unpack part 1 first!"
  19.      exit 1; fi
  20. ( read Scheck
  21.   if test "$Scheck" != $CurArch
  22.   then echo "Please unpack part $Scheck next!"
  23.        exit 1;
  24.   else exit 0; fi
  25. ) < s2_seq_.tmp || exit 1
  26. echo "x - Continuing file src/kdsi/kdsi.c"
  27. sed 's/^X//' << 'SHAR_EOF' >> src/kdsi/kdsi.c
  28. X    tot_cdline = tot_cmline = tot_bkline = tot_comment = 0;
  29. X    while ( (fp = nextfp(argc, argv, &filename)) != FNULL )
  30. X    {
  31. X        cod_linect = com_linect = blnk_linect = comment_ct = 0;
  32. X        filecount++;
  33. X
  34. X        while ( (input = GetChar(fp)) != STOP_INPUT )
  35. X        {
  36. X            switch ( input )
  37. X            {
  38. X            case NEWLINE:
  39. X                if ( statevar == Code )
  40. X                    cod_linect++;
  41. X                else if ( statevar == Comment )
  42. X                    com_linect++;
  43. X                /* state is quiescent */
  44. X                else if ( laststate == Comment )
  45. X                {
  46. X                    /* if is supposed to catch cases where a comment
  47. X                     * follows a line of code
  48. X                     */
  49. X                    if ( following_com )
  50. X                        cod_linect++;
  51. X                    else
  52. X                        com_linect++;
  53. X                }
  54. X                else
  55. X                    blnk_linect++;
  56. X                if ( statevar != Comment )
  57. X                {
  58. X                    laststate = Quiescent;
  59. X                    statevar = Quiescent;
  60. X                }
  61. X                following_com = False;
  62. X                break;
  63. X            case START_COMMENT:
  64. X                laststate = statevar;
  65. X                statevar = Comment;
  66. X                break;
  67. X            case END_COMMENT:
  68. X                comment_ct++;
  69. X                    /* if true, is a comment on same line as code */
  70. X                if ( laststate == Code )
  71. X                    following_com = True;
  72. X
  73. X                laststate = Comment;
  74. X                statevar = Quiescent;
  75. X                break;
  76. X            case MISC_CHARACTER:
  77. X                if ( statevar == Quiescent )
  78. X                {
  79. X                    laststate = statevar;
  80. X                    statevar = Code;
  81. X                }
  82. X                break;
  83. X            default:
  84. X                fprintf(stderr, "kdsi: illegal token (%d) returned from GetChar\n", input);
  85. X                exit(1);
  86. X                break;
  87. X
  88. X            }
  89. X        }
  90. X        if ( !only_stdin )
  91. X            printf("%8ld %8ld %8ld %7ld  %s\n",
  92. X                cod_linect, blnk_linect, com_linect, comment_ct,
  93. X                filename);
  94. X        else
  95. X            printf("%8ld %8ld %8ld %7ld\n",
  96. X                cod_linect, blnk_linect, com_linect, comment_ct);
  97. X        tot_cdline += cod_linect;
  98. X        tot_cmline += com_linect;
  99. X        tot_bkline += blnk_linect;
  100. X        tot_comment += comment_ct;
  101. X    }
  102. X    if ( !only_stdin && filecount > 1 )
  103. X        printf("%8ld %8ld %8ld %7ld  total\n",
  104. X            tot_cdline, tot_bkline, tot_cmline, tot_comment);
  105. X    exit(0);
  106. X}
  107. X
  108. XToken
  109. XGetChar( file )
  110. X    FILE    *file;
  111. X{
  112. X    /* return token for char type, taking into account comment delims */
  113. X    /* ignores spaces and tabs */
  114. X
  115. X    register int    c;
  116. X    register Token    retval;
  117. X    static int    buf;
  118. X    static Bool    inbuf = False;
  119. X
  120. X    do
  121. X    {
  122. X        if ( inbuf )
  123. X        {
  124. X            c = buf;
  125. X            inbuf = False;
  126. X        }
  127. X        else
  128. X            c = getc(file);
  129. X        
  130. X        switch ( c )
  131. X        {
  132. X        case EOF:
  133. X            retval = STOP_INPUT;
  134. X            break;
  135. X        case '\n':
  136. X            retval = NEWLINE;
  137. X            break;
  138. X        case '/':
  139. X            buf = getc( file );
  140. X            if ( buf == '*' )
  141. X                retval = START_COMMENT;
  142. X            else
  143. X            {
  144. X                inbuf = True;
  145. X                retval = MISC_CHARACTER;
  146. X            }
  147. X            break;
  148. X        case '*':
  149. X            buf = getc( file );
  150. X            if ( buf == '/' )
  151. X                retval = END_COMMENT;
  152. X            else
  153. X            {
  154. X                inbuf = True;
  155. X                retval = MISC_CHARACTER;
  156. X            }
  157. X            break;
  158. X        case ' ':
  159. X        case '\t':
  160. X            retval = WHITE_SPACE;
  161. X            break;
  162. X        default:
  163. X            retval = MISC_CHARACTER;
  164. X        }
  165. X    }
  166. X    while ( retval == WHITE_SPACE );
  167. X
  168. X    return (retval);
  169. X}
  170. X
  171. XFILE *
  172. Xnextfp( argc, argv, p_filename)
  173. X    int    argc;
  174. X    char    *argv[];
  175. X    char    **p_filename;
  176. X{
  177. X    /* looks through parameters trying to return next FILE * to next
  178. X     * specified file
  179. X     * passes back a pointer to the filename as a side effect
  180. X     */
  181. X    
  182. X    static Bool    first = True;
  183. X    static int    index = 1;
  184. X    static FILE    *result = FNULL;
  185. X
  186. X    *p_filename = CNULL;
  187. X
  188. X    if ( result != FNULL )
  189. X    {
  190. X        fclose( result );
  191. X        result = FNULL;
  192. X    }
  193. X    while ( index < argc && *argv[index] == '-' )
  194. X        index++;
  195. X
  196. X    if ( index < argc )
  197. X    {
  198. X        if ( (result = fopen( argv[index], "r")) == NULL )
  199. X        {
  200. X            fprintf(stderr, "%s: unable to open %s for read\n",
  201. X                argv[0], argv[index]);
  202. X            exit(1);
  203. X        }
  204. X        else
  205. X            *p_filename = argv[index];
  206. X        index++;
  207. X    }
  208. X    if ( first )
  209. X    {
  210. X        /* if no files specified, read from stdin */
  211. X        /* filename remains null */
  212. X        if ( result == FNULL )
  213. X        {
  214. X            result = stdin;
  215. X            only_stdin = True;
  216. X        }
  217. X        first = False;
  218. X    }
  219. X    return ( result );
  220. X}
  221. SHAR_EOF
  222. echo "File src/kdsi/kdsi.c is complete"
  223. chmod 0644 src/kdsi/kdsi.c || echo "restore of src/kdsi/kdsi.c fails"
  224. echo "x - extracting src/kdsi/test.result (Text)"
  225. sed 's/^X//' << 'SHAR_EOF' > src/kdsi/test.result
  226. X     153       25       20      11  test1.c
  227. X     233       22        4       4  test2.y
  228. X     311       44        8      22  test3.c
  229. X     697       91       32      37  total
  230. SHAR_EOF
  231. chmod 0644 src/kdsi/test.result || echo "restore of src/kdsi/test.result fails"
  232. echo "x - extracting src/mccabe/Makefile (Text)"
  233. sed 's/^X//' << 'SHAR_EOF' > src/mccabe/Makefile
  234. X# makefile for mccabe utilities
  235. X
  236. XBIN=../bin
  237. XTEST=../testfiles
  238. X
  239. X
  240. Xall:    mccabe
  241. X
  242. Xmccabe:    mccabe.sh
  243. X    cp mccabe.sh mccabe
  244. X    chmod u+x mccabe
  245. X
  246. Xinstall:    all
  247. X    mv mccabe $(BIN)/mccabe
  248. X    chmod 755 $(BIN)/mccabe
  249. X
  250. Xclean:
  251. X    -rm -f mccabe _test
  252. X    
  253. Xtest:
  254. X    @echo results of this command should be the same as test.result
  255. X    @cp $(TEST)/test1.c $(TEST)/test2.y $(TEST)/test3.c .
  256. X    mccabe test1.c test2.y test3.c > _test
  257. X    diff _test test.result
  258. X    @/bin/rm -f test1.c test2.y test3.c
  259. SHAR_EOF
  260. chmod 0644 src/mccabe/Makefile || echo "restore of src/mccabe/Makefile fails"
  261. echo "x - extracting src/mccabe/mccabe.sh (Text)"
  262. sed 's/^X//' << 'SHAR_EOF' > src/mccabe/mccabe.sh
  263. X:
  264. X# determine function complexity based on Mccabe model of program complexity
  265. X# anything greater than 10 is usually considered bad, or at least questionable
  266. X#
  267. X# originally written by Rick Cobb, modified by Brian Renaud to add out
  268. X# of function complexity detection and to fix some minor bugs
  269. X
  270. X# NOTE the beginning and ending braces "{}" in a function must be at the
  271. X# same indent level, or this tools will NOT work!!
  272. X
  273. X# heuristics for function declaration detection:
  274. X#    Handles three conventions:
  275. X#
  276. X#    |int foo()
  277. X#    |    char *
  278. X#    |    {
  279. X
  280. X#    |int foo()
  281. X#    |char *
  282. X#    |[    ]*{
  283. X
  284. X#    or the preferred
  285. X#    int
  286. X#    foo()
  287. X#    []*{
  288. X
  289. X
  290. Xif [ $# = 0 ]
  291. Xthen
  292. X    echo "usage: mccabe [-n] file [file]" > /dev/tty
  293. X    exit 1
  294. Xfi
  295. X
  296. X# the -n flag (No Header) is useful if you are using this to produce data for
  297. X# other tools
  298. X
  299. XHEADER=1
  300. Xif [ $1 = "-n" ]
  301. Xthen
  302. X    HEADER=0
  303. X    shift
  304. Xfi
  305. X
  306. Xif [ $HEADER = "1" ]
  307. Xthen
  308. X    echo "File              Name               Complexity    No. of returns"
  309. X    echo "--------------    ---------------    ----------    --------------"
  310. Xfi
  311. X
  312. Xfor file in $*
  313. Xdo
  314. X    stripcom ${file} |\
  315. X    awk 'BEGIN    {
  316. X    File = "'"${file}"'";
  317. X    Header = '${HEADER}';
  318. X    gotfunction = "FALSE";
  319. X    infunction = "FALSE";
  320. X    nofunc = "***"
  321. X    complexity[nofunc] = 1;
  322. X    returns[nofunc] = 0;
  323. X    casecount[nofunc] = 0;
  324. X    }
  325. X
  326. X# Should recognize the actual function:
  327. X/^[_a-zA-Z][_a-zA-Z]*.*\(.*\)[     ]*$/ && $1 !~ /extern/ && infunction == "FALSE"{
  328. X
  329. X    gotfunction="TRUE";
  330. X
  331. X    # strip off parens (so we can make PARMS statement)
  332. X    endpos = index($0,"(");
  333. X    funcname = substr($0,1,endpos-1);
  334. X
  335. X    # strip off beginning declaratory stuff (if any)
  336. X    parts = split(funcname,funky,"     ");
  337. X    funcname = funky[parts];
  338. X    complexity[funcname] = 1;    # default complexity is 1
  339. X    casecount[funcname] = 0;
  340. X    switchcount[funcname] = 0;
  341. X
  342. X    next;
  343. X    }
  344. X
  345. X#do not count preprocessor lines
  346. X/^#/    { next; }
  347. X
  348. X# find end of formal parameters
  349. X
  350. Xgotfunction == "TRUE" && /[     ]*{/    {
  351. X    gotfunction = "FALSE";
  352. X    infunction = "TRUE";
  353. X
  354. X    depth = index($0,"{");
  355. X    next;
  356. X    }
  357. X
  358. Xinfunction == "TRUE" && /(^|[ \t;])(if|else|while|for)($|[ \t(])/ {
  359. X    complexity[funcname]++;
  360. X    }
  361. X
  362. Xinfunction == "TRUE" && /(^|[ \t;])(switch)($|[ \t(])/ {
  363. X    switchcount[funcname]++;
  364. X    }
  365. X
  366. Xinfunction == "TRUE" && /(^|[ \t;])(case|default[ \t]*:)($|[ \t])/ {
  367. X    casecount[funcname]++;
  368. X    }
  369. X
  370. Xinfunction == "TRUE" && /(^|[ \t;])return([ \t(]|$)/    {
  371. X    returns[funcname]++;
  372. X    }
  373. X
  374. Xinfunction == "TRUE" && /(^|[ \t;])exit($|[ \t(])/    {
  375. X    returns[funcname]++;
  376. X    }
  377. X
  378. Xinfunction == "TRUE" && /}/    { 
  379. X    if (index($0,"}") == depth)
  380. X        {
  381. X        infunction = "FALSE";
  382. X        gotfunction = "FALSE";
  383. X        }
  384. X    next;
  385. X    }
  386. X
  387. Xinfunction == "FALSE" && /(^|[ \t;])(if|else|while|for)($|[ \t(])/ {
  388. X    complexity[nofunc]++;
  389. X    }
  390. X
  391. Xinfunction == "FALSE" && /(^|[ \t;])(case|default[ \t]*:)($|[ \t])/ {
  392. X    casecount[nofunc]++;
  393. X    }
  394. X
  395. Xinfunction == "FALSE" && /(^|[ \t;])return([ \t(]|$)/    {
  396. X    returns[nofunc]++;
  397. X    }
  398. X
  399. Xinfunction == "FALSE" && /(^|[ \t;])exit($|[ \t(])/    {
  400. X    returns[nofunc]++;
  401. X    }
  402. X
  403. XEND    {
  404. X    count = 0;
  405. X    for (func in complexity)
  406. X        {
  407. X        if ( func == nofunc &&\
  408. X             complexity[ func ]    == 1 &&\
  409. X             casecount[ func ]    == 0 &&\
  410. X             returns[ func ]    == 0)
  411. X            continue;
  412. X        count++;
  413. X        complex=complexity[func];
  414. X        cases=casecount[func];
  415. X
  416. X        if ( Header )
  417. X            printf("%-14s\t%-15s\t%10d\t%10d\n",\
  418. X                File, func, complex + cases, returns[func]);
  419. X        else
  420. X            printf("%s\t%s\t%d\t%d\n",\
  421. X                File, func, complex + cases, returns[func]);
  422. X        }
  423. X    if ( count == 0 )
  424. X        {
  425. X        # this means that no functions were found in the file
  426. X        if ( Header )
  427. X            printf("%-14s\t%-15s\t%10d\t%10d\n",\
  428. SHAR_EOF
  429. echo "End of part 9"
  430. echo "File src/mccabe/mccabe.sh is continued in part 10"
  431. echo "10" > s2_seq_.tmp
  432. exit 0
  433.  
  434.  
  435.