home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1995 August / NEBULA.mdf / Apps / DevTools / CodeCounter / Source / count.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-30  |  5.6 KB  |  268 lines

  1. /* counts number of statements, lines of code, comments, comment lines
  2.  * and blank lines
  3. ***************************************************************************/
  4. /***************************************************************************
  5. * kdsi has been modified to include headers (titles) above statistics      *
  6. * scott maretick                               *    
  7. ***************************************************************************/
  8. /***************************************************************************
  9. * kdsi has been modified to also count '//' lines as comments for C++ or   *
  10. * Objective-C                                   *    
  11. * scott maretick                               *    
  12. ***************************************************************************/
  13.  
  14. #include <stdio.h>
  15.  
  16. typedef    int    Token;
  17. #define    STOP_INPUT    0
  18. #define    NEWLINE    1
  19. #define START_COMMENT    2
  20. #define END_COMMENT    3
  21. #define    MISC_CHARACTER    4
  22. #define WHITE_SPACE    5
  23.  
  24. typedef char    Bool;
  25. #define True    1
  26. #define False    0
  27.  
  28. typedef int    State;
  29. #define    Code    0
  30. #define Comment    1
  31. #define Quiescent    2
  32.  
  33. #define FNULL    ( (FILE *) 0)
  34. #define CNULL    ( (char *) 0)
  35.  
  36. Bool    only_stdin = False;        /* true if reading from stdin */
  37.  
  38.  char objc_comm = 'N';
  39.  
  40. main(argc, argv)
  41.     int    argc;
  42.     char    *argv[];
  43. {
  44.     Token    GetChar();
  45.     FILE    *nextfp();
  46.     register Token    input;
  47.     register State    statevar = Quiescent, laststate = Quiescent;
  48.     FILE    *fp;
  49.     char    *filename;
  50.     int    filecount = 0;
  51.     long    cod_linect, com_linect, blnk_linect;
  52.     long    tot_cdline, tot_cmline, tot_bkline;
  53.     long    grand_tot_cdline, grand_tot_cmline, grand_tot_bkline;
  54.     Bool    following_com = False;
  55.  
  56.     tot_cdline = tot_cmline = tot_bkline = 0;
  57.     grand_tot_cdline = grand_tot_cmline = grand_tot_bkline = 0;
  58.     while ( (fp = nextfp(argc, argv, &filename)) != FNULL )
  59.     {
  60.         cod_linect = com_linect = blnk_linect = 0;
  61.         filecount++;
  62.  
  63.         while ( (input = GetChar(fp)) != STOP_INPUT )
  64.         {
  65.             switch ( input )
  66.             {
  67.             case NEWLINE:
  68.                 if ( statevar == Code && objc_comm == 'N')
  69.                     cod_linect++;
  70.                 else if ( statevar == Comment || objc_comm == 'Y')
  71.                     {com_linect++;
  72.                     objc_comm = 'N';}
  73.                 /* state is quiescent */
  74.                 else if ( laststate == Comment )
  75.                 {
  76.                     /* if is supposed to catch cases where a comment
  77.                      * follows a line of code
  78.                      */
  79.                     if ( following_com ) 
  80.                         cod_linect++;
  81.                     else
  82.                         com_linect++;
  83.                 }
  84.                 else
  85.                     blnk_linect++;
  86.                 if ( statevar != Comment )
  87.                 {
  88.                     laststate = Quiescent;
  89.                     statevar = Quiescent;
  90.                 }
  91.                 following_com = False;
  92.                 break;
  93.             case START_COMMENT:
  94.                 laststate = statevar;
  95.                 statevar = Comment;
  96.                 break;
  97.             case END_COMMENT:
  98.                     /* if true, is a comment on same line as code */
  99.                 if ( laststate == Code )
  100.                     following_com = True;
  101.  
  102.                 laststate = Comment;
  103.                 statevar = Quiescent;
  104.                 break;
  105.             case MISC_CHARACTER:
  106.                 if ( statevar == Quiescent )
  107.                 {
  108.                     laststate = statevar;
  109.                     statevar = Code;
  110.                 }
  111.                 break;
  112.             default:
  113.                 fprintf(stderr, "kdsi: illegal token (%d) returned from GetChar\n", input);
  114.                 exit(1);
  115.                 break;
  116.  
  117.             }
  118.         }
  119.         if ( !only_stdin ) {
  120.  
  121.         printf("     LOC     BLANKS  COMM   PGM\n");
  122.             printf("%8ld %8ld %6ld    %s\n",
  123.                 cod_linect, blnk_linect, com_linect,
  124.                 filename); }
  125.         else {
  126.         printf("     LOC     BLANKS  COMM   PGM\n");
  127.             printf("%8ld %8ld %6ld    %s\n",
  128.                 cod_linect, blnk_linect, com_linect); }
  129.         tot_cdline += cod_linect;
  130.         tot_cmline += com_linect;
  131.         tot_bkline += blnk_linect;
  132.  
  133.         grand_tot_cdline += tot_cdline;
  134.         grand_tot_cmline += tot_cmline;
  135.         grand_tot_bkline += tot_bkline;
  136.     }
  137.     if ( !only_stdin && filecount > 1 ) {
  138.  
  139.         printf("     TOT       TOT    TOT   TOT       \n");
  140.         printf("     LOC     BLANKS  COMM   PGM\n");
  141.         printf("%8ld %8ld %6ld   total\n",
  142.             tot_cdline, tot_bkline, tot_cmline); }
  143.  
  144. /*    if (STOP_INPUT) {
  145.  
  146.         printf("     GT_LOC     GT_BLANKS  GT_COMM   PGM\n");
  147.         printf("%8ld %8ld %6ld   total\n",
  148.         grand_tot_cdline, grand_tot_bkline, grand_tot_cmline); }*/
  149.     exit(0);
  150. }
  151.  
  152. Token
  153. GetChar( file )
  154.     FILE    *file;
  155. {
  156.     /* return token for char type, taking into account comment delims */
  157.     /* ignores spaces and tabs */
  158.  
  159.     register int    c;
  160.     register Token    retval;
  161.     static int    buf;
  162.     static Bool    inbuf = False;
  163.  
  164.     do
  165.     {
  166.         if ( inbuf )
  167.         {
  168.             c = buf;
  169.             inbuf = False;
  170.         }
  171.         else
  172.             c = getc(file);
  173.         
  174.         switch ( c )
  175.         {
  176.         case EOF:
  177.             retval = STOP_INPUT;
  178.             break;
  179.         case '\n':
  180.             retval = NEWLINE;
  181.             break; 
  182.         case '/':
  183.             buf = getc( file );
  184.             if ( buf == '*' )
  185.                 retval = START_COMMENT;
  186.             else if (buf == '/' ) {
  187.                 objc_comm = 'Y';
  188.                 retval = END_COMMENT; }
  189.             else
  190.             {
  191.                 inbuf = True;
  192.                 retval = MISC_CHARACTER;
  193.             }
  194.             break;
  195.         case '*':
  196.             buf = getc( file );
  197.             if ( buf == '/' )
  198.                 retval = END_COMMENT;
  199.             else
  200.             {
  201.                 inbuf = True;
  202.                 retval = MISC_CHARACTER;
  203.             }
  204.             break;
  205.         case ' ':
  206.         case '\t':
  207.             retval = WHITE_SPACE;
  208.             break;
  209.         default:
  210.             retval = MISC_CHARACTER;
  211.         }
  212.     }
  213.     while ( retval == WHITE_SPACE );
  214.  
  215.     return (retval);
  216. }
  217.  
  218. FILE *
  219. nextfp( argc, argv, p_filename)
  220.     int    argc;
  221.     char    *argv[];
  222.     char    **p_filename;
  223. {
  224.     /* looks through parameters trying to return next FILE * to next
  225.      * specified file
  226.      * passes back a pointer to the filename as a side effect
  227.      */
  228.     
  229.     static Bool    first = True;
  230.     static int    index = 1;
  231.     static FILE    *result = FNULL;
  232.  
  233.     *p_filename = CNULL;
  234.  
  235.     if ( result != FNULL )
  236.     {
  237.         fclose( result );
  238.         result = FNULL;
  239.     }
  240.     while ( index < argc && *argv[index] == '-' )
  241.         index++;
  242.  
  243.     if ( index < argc )
  244.     {
  245.         if ( (result = fopen( argv[index], "r")) == NULL )
  246.         {
  247.             fprintf(stderr, "%s: unable to open %s for read\n",
  248.                 argv[0], argv[index]);
  249.             exit(1);
  250.         }
  251.         else
  252.             *p_filename = argv[index];
  253.         index++;
  254.     }
  255.     if ( first )
  256.     {
  257.         /* if no files specified, read from stdin */
  258.         /* filename remains null */
  259.         if ( result == FNULL )
  260.         {
  261.             result = stdin;
  262.             only_stdin = True;
  263.         }
  264.         first = False;
  265.     }
  266.     return ( result );
  267. }
  268.