Subject: v20i015: Tools for generating software metrics, Part08/14 Newsgroups: comp.sources.unix Sender: sources Approved: rsalz@uunet.UU.NET Submitted-by: Brian Renaud Posting-number: Volume 20, Issue 15 Archive-name: metrics/part08 ---- Cut Here and unpack ---- #!/bin/sh # this is part 8 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file src/halstead/c_halsfilt_c continued # CurArch=8 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file src/halstead/c_halsfilt_c" sed 's/^X//' << 'SHAR_EOF' >> src/halstead/c_halsfilt_c X# ifdef LEXDEBUG X if(debug){ X fprintf(yyout,"try fall back character "); X allprint(YYU(yymatch[yych])); X putchar('\n'); X } X# endif X if(yyt <= yytop && yyt->verify+yysvec == yystate){ X if(yyt->advance+yysvec == YYLERR) /* error transition */ X {unput(*--yylastch);break;} X *lsp++ = yystate = yyt->advance+yysvec; X goto contin; X } X } X if ((yystate = yystate->yyother) && (yyt= yystate->yystoff) != yycrank){ X# ifdef LEXDEBUG X if(debug)fprintf(yyout,"fall back to state %d\n",yystate-yysvec-1); X# endif X goto tryagain; X } X# endif X else X {unput(*--yylastch);break;} X contin: X# ifdef LEXDEBUG X if(debug){ X fprintf(yyout,"state %d char ",yystate-yysvec-1); X allprint(yych); X putchar('\n'); X } X# endif X ; X } X# ifdef LEXDEBUG X if(debug){ X fprintf(yyout,"stopped at %d with ",*(lsp-1)-yysvec-1); X allprint(yych); X putchar('\n'); X } X# endif X while (lsp-- > yylstate){ X *yylastch-- = 0; X if (*lsp != 0 && (yyfnd= (*lsp)->yystops) && *yyfnd > 0){ X yyolsp = lsp; X if(yyextra[*yyfnd]){ /* must backup */ X while(yyback((*lsp)->yystops,-*yyfnd) != 1 && lsp > yylstate){ X lsp--; X unput(*yylastch--); X } X } X yyprevious = YYU(*yylastch); X yylsp = lsp; X yyleng = yylastch-yytext+1; X yytext[yyleng] = 0; X# ifdef LEXDEBUG X if(debug){ X fprintf(yyout,"\nmatch "); X sprint(yytext); X fprintf(yyout," action %d\n",*yyfnd); X } X# endif X return(*yyfnd++); X } X unput(*yylastch); X } X if (yytext[0] == 0 /* && feof(yyin) */) X { X yysptr=yysbuf; X return(0); X } X yyprevious = yytext[0] = input(); X if (yyprevious>0) X output(yyprevious); X yylastch=yytext; X# ifdef LEXDEBUG X if(debug)putchar('\n'); X# endif X } X } Xyyback(p, m) X int *p; X{ Xif (p==0) return(0); Xwhile (*p) X { X if (*p++ == m) X return(1); X } Xreturn(0); X} X /* the following are only used in the lex library */ Xyyinput(){ X return(input()); X } Xyyoutput(c) X int c; { X output(c); X } Xyyunput(c) X int c; { X unput(c); X } SHAR_EOF echo "File src/halstead/c_halsfilt_c is complete" chmod 0644 src/halstead/c_halsfilt_c || echo "restore of src/halstead/c_halsfilt_c fails" echo "x - extracting src/halstead/halstead.sh (Text)" sed 's/^X//' << 'SHAR_EOF' > src/halstead/halstead.sh X: compute halstead volume of input X# see DeMarco "Controlling Software Projects, Management, Measurement X# and Estimation", appendix D X# algorithm X# strip comments X# remove strings X# remove delimiters X# deal with *++var and *--var usages X# break input into tokens X# sort - to produce total number of tokens X# uniq - to get size of vocabulary X# volume = * log2 ( vocabulary size ) X X# n1 == number of unique operators X# n2 == number of unique operands X# N1 == number of total operators X# N2 == number of total operands X XN1=/tmp/$$.N1 XN2=/tmp/$$.N2 Xn1=/tmp/$$.n1 Xn2=/tmp/$$.n2 X Xtrap '/bin/rm -f ${n1} ${n2} ${N1} ${N2} ; exit 1' 1 2 15 X Xif [ $# -lt 1 ] Xthen X echo "usage: $0 []" X exit 1 Xfi X Xfor file in $* Xdo X stripcom ${file} | stripstr |\ X c_halsfilt 2> ${N1} |\ X awk ' { for ( i = 1; i <= NF; i++) print $i; } ' |\ X sort > ${N2} X X sort -u ${N1} > ${n1} X uniq < ${N2} > ${n2} X X wc -l ${n1} ${n2} ${N1} ${N2} |\ X awk ' X BEGIN { X File = "'"${file}"'"; X if ( !getline ) X printf("%s: no line count for n1\n", "'"$0"'"); X u_opators = $1; X X if ( !getline ) X printf("%s: no line count for n2\n", "'"$0"'"); X u_opands = $1; X X if ( !getline ) X printf("%s: no line count for N1\n", "'"$0"'"); X t_opators = $1; X X if ( !getline ) X printf("%s: no line count for N2\n", "'"$0"'"); X t_opands = $1; X X # program length: N = N1 + N2 X # X pg_length = t_opators + t_opands; X X # program volume: V = N log (n1 + n2) X # X pg_volume = pg_length * (log(u_opators + u_opands)/log(2)); X X # program level: L = (2/n1) * (n2/N2) X # 2 is number of operators in smallest possible program X # X pg_level = (2 / u_opators) * (u_opands / t_opands); X X # estimated effective mental discriminations: E^ = V / L X # X mental_disc = pg_volume / pg_level; X X # estimated mental discriminations per second in C: 50 X # I assume performance is normally distributed X # therefore per hour: 180,000 X # so estimated time to program: T^ = E^ / 180,000 X # DOES NOT SEEM VERY ACCURATE FOR LARGE PROGRAMS X # ALL TIME STUFF REMOVED VIA COMMENTS X #time = mental_disc / 180000; X X # print File N V L E^ T^ X #printf("%s\t%d\t%.0f\t%.6f\t%.0f\t%.1f\n",\ X # File, pg_length, pg_volume, pg_level, mental_disc,time); X X # print File N V L E^ X printf("%s\t%d\t%.0f\t%.6f\t%.0f\n",\ X File, pg_length, pg_volume, pg_level, mental_disc); X exit; X } X ' Xdone X X/bin/rm ${n1} ${n2} ${N1} ${N2} Xexit 0 SHAR_EOF chmod 0644 src/halstead/halstead.sh || echo "restore of src/halstead/halstead.sh fails" echo "x - extracting src/halstead/test.result (Text)" sed 's/^X//' << 'SHAR_EOF' > src/halstead/test.result Xtest1.c 619 4130 0.014966 275975 Xtest2.y 1003 7043 0.017320 406675 Xtest3.c 1234 8652 0.008107 1067162 SHAR_EOF chmod 0644 src/halstead/test.result || echo "restore of src/halstead/test.result fails" echo "x - extracting src/halstead/README (Text)" sed 's/^X//' << 'SHAR_EOF' > src/halstead/README XOn SCO Xenix '286 Version 2.2.1, a Sun4 and a Sun386i "make test" Xproduced the following results for test3.c: X X test3.c 1234 8652 0.008107 1067161 X XThe ``mental discriminations'' value (1067161) is one less than the Xstandard. Since the validity of this number is questionable, I guess Xit's no big deal. SHAR_EOF chmod 0644 src/halstead/README || echo "restore of src/halstead/README fails" echo "x - extracting src/kdsi/Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > src/kdsi/Makefile X# makefile for kdsi a source lines of code counter X XBIN=../bin XTEST=../testfiles X XCFLAGS= -O XLDFLAGS= X Xkdsi: X $(CC) $(CFLAGS) $(LDFLAGS) -o kdsi kdsi.c X Xinstall: X mv kdsi $(BIN)/kdsi X chmod 755 $(BIN)/kdsi X Xclean: X -rm -f core kdsi *.o _test X Xtest: X @echo results of this command should be the same as test.result X @cp $(TEST)/test1.c $(TEST)/test2.y $(TEST)/test3.c . X kdsi test1.c test2.y test3.c > _test X diff _test test.result X @/bin/rm -f test1.c test2.y test3.c SHAR_EOF chmod 0644 src/kdsi/Makefile || echo "restore of src/kdsi/Makefile fails" echo "x - extracting src/kdsi/kdsi.c (Text)" sed 's/^X//' << 'SHAR_EOF' > src/kdsi/kdsi.c X/* counts number of statements, lines of code, comments, comment lines X * and blank lines X */ X/*************************************************************************** X* kdsi is written by Brian Renaud, is in the public domain, and * X* may be used by any person or organization, in any way and for any * X* purpose. * X* * X* There is no warranty of merchantability nor any warranty of fitness for * X* a particular purpose nor any other warranty, either express or implied, * X* as to the accuracy of the enclosed materials or as to their suitability * X* for any particular purpose. Accordingly, I assume no responsibility * X* for their use by the recipient. Further, I assume no obligation to * X* furnish any assistance of any kind whatsoever, or to furnish any * X* additional information or documentation. * X* * X* address as of July 1988: bdr%huron.uucp@umix.cc.umich.edu also known as: * X* {ames, apollo, rutgers, uunet}!umix!huron!bdr * X***************************************************************************/ X X#include X Xtypedef int Token; X#define STOP_INPUT 0 X#define NEWLINE 1 X#define START_COMMENT 2 X#define END_COMMENT 3 X#define MISC_CHARACTER 4 X#define WHITE_SPACE 5 X Xtypedef char Bool; X#define True 1 X#define False 0 X Xtypedef int State; X#define Code 0 X#define Comment 1 X#define Quiescent 2 X X#define FNULL ( (FILE *) 0) X#define CNULL ( (char *) 0) X XBool only_stdin = False; /* true if reading from stdin */ X Xmain(argc, argv) X int argc; X char *argv[]; X{ X Token GetChar(); X FILE *nextfp(); X register Token input; X register State statevar = Quiescent, laststate = Quiescent; X FILE *fp; X char *filename; X int filecount = 0; X long cod_linect, com_linect, blnk_linect, comment_ct; X long tot_cdline, tot_cmline, tot_bkline, tot_comment; X Bool following_com = False; X SHAR_EOF echo "End of part 8" echo "File src/kdsi/kdsi.c is continued in part 9" echo "9" > s2_seq_.tmp exit 0