User ID:
Password:
Remember Me:
Forgot Password?
Not a member?
Click here for more information and to register.

    Utility to Product Source Code Statistics



    This utility is for developers that need to obtain statistics concerning their source code. It will scan a directory structure and obtain all available statistics information from the source code such as total code lines, comments lines, headers lines, code and resources lines. Scanning can be recursive and countable files extensions can de defined.

    // Copyright by Valery R. Kim, 20.01.2000. Freeware.
    
    #include 
    #include 
    #include 
    #include 
    
    // White space delimiters
    #define STR_WHITE_SPACE "/r/n /t,;"
    
    // Structure accumulating statistics information
    typedef struct _SCAN_INFO
    {
     unsigned long lHeaders;
     unsigned long lCode;
     unsigned long lResources;
     unsigned long lLines;
     unsigned long lComments; 
    
     _SCAN_INFO() { lLines=lComments=lResources=lCode=lHeaders=0; }
    
     _SCAN_INFO& operator+(_SCAN_INFO& ScanInfo)
     {
      lLines+=ScanInfo.lLines;
      lComments+=ScanInfo.lComments;  
      lHeaders+=ScanInfo.lHeaders;
      lCode+=ScanInfo.lCode;
      lResources+=ScanInfo.lResources;
      return *this;
     }
     _SCAN_INFO& operator+=(_SCAN_INFO& ScanInfo)
     {
      lLines+=ScanInfo.lLines;
      lComments+=ScanInfo.lComments;
      lHeaders+=ScanInfo.lHeaders;
      lCode+=ScanInfo.lCode;
      lResources+=ScanInfo.lResources;
      return *this;
     }
    
    } SCAN_INFO, *PSCAN_INFO;
    
    // Default predefined countable extensions
    static const char pPredefinedExts[]={"c cpp h hpp rc"};
    
    // Function filling template vector by countable 
    //files extensions
    template void FillExts(CArray& pDest, char** pExts)
    {
     char* pItem=NULL;
     int  i=0;
     while(pItem=pExts[i]){
      pDest.Add(T(pExts[i]));
      i++;
     }
    }
    
    // Function filling template array from by default countable extensions
    template void FillExts(CArray& pDest, const char pSrc[])
    {
     char szBuf[_MAX_PATH];
     strcpy(szBuf, pSrc);
    
    // Looking for substrings devided by white space
     char* pItem=strtok(szBuf, STR_WHITE_SPACE); 
     while(pItem){
      pDest.Add(T(pItem));
      pItem=strtok(NULL, STR_WHITE_SPACE);
     }
    }
    
    // Function scanning file for statistics information
    void ScanFile(CString sFileName, PSCAN_INFO pScanInfo, 
    unsigned long* plType)
    {
     FILE *f=fopen(sFileName, "r");
     
     if(!f) return;
    
     char szBuf[4096];
    
     // Loop for file text lines
     while(fgets(szBuf, sizeof(szBuf), f)){
      pScanInfo->lLines++;
    
      (*plType)++;
    
      // Trim left leading white spaces
      CString s(szBuf);
      s.TrimLeft();
    
      if(s.Left(2)=="//") pScanInfo->lComments++;
     }
    
     fclose(f);
    }
    
    // Recursive function looping by subfolders
    template void FoldersLoop(CString sDir, CArray& pExts, 
    bool bRecursive, SCAN_INFO& FolderScanInfo)
    {
     // Don't make statistics for folders "." and ".."
     if(sDir[sDir.GetLength()-1]=='.') return;
    
     WIN32_FIND_DATA findData;
    
     HANDLE hFind=FindFirstFile(sDir+"//*.*", &findData);
    
     if(hFind==INVALID_HANDLE_VALUE){
    
      // No files in this folder
      return;
     } 
    
     CArray pFiles;
     CArray pTypes;
    
     do{
      if(findData.dwFileAttributes & 
      FILE_ATTRIBUTE_DIRECTORY && bRecursive){
    
       // Scan this folder
       FoldersLoop(sDir+"//"+findData.cFileName, pExts, 
        bRecursive, FolderScanInfo);
      }
      else {
    
       // Get file extension
       CString sFileName(findData.cFileName);
    
       CString sExt=sFileName.Right(sFileName.GetLength()
        -sFileName.Find(".")-1);
    
       if(sExt!=""){
    
        sExt.MakeLower();
    
        // Look if this extension is countable
        for(int i=0; i// File satisfies conditions for extension
          pFiles.Add(sDir+"//"+findData.cFileName);
    
    
          // 0-length offset from structure addr
          if(sExt=="hpp" || sExt=="h") pTypes.Add(0);        
    
          // 1-length offset from structure addr
          else if(sExt=="cpp" || sExt=="c") pTypes.Add(1);   
    
          // 2-length offset from structure addr
          else if(sExt=="rc") pTypes.Add(2);                 
         }
       }
      }  
     } while(FindNextFile(hFind, &findData));
    
     cout << sDir;
    
     // If we've found anything
     if(pFiles.GetSize()){
    
      cout << endl;
      for(int i=0; i        
    
    
    
    
    
    
    // Scan this file according to it's type
       ScanFile(pFiles[i], &ScanInfo, &(ScanInfo.lHeaders)+pTypes[i]);
    
       FolderScanInfo+=ScanInfo;
    
       cout << ".";
      }
     }
    
     cout << endl;
    
     // Free templates data memory
     pFiles.RemoveAll();
     pTypes.RemoveAll();
    }
    
    // Main entry point
    int main(int argc, char* argv[])
    {
     // Check parameters list
     if(argc<=1){
      cout << "Bad arguments list. Format is as follows:" << endl
           << "StatCode.exe <dir_name> [-R] [exts]" << endl
           << "  key R - means recursive statistics" << endl
           << "  exts - list of countable files extensions divided by "
                    "white spaces." << endl
           << "  By default *.cpp, *.c, *.h, *.cpp, *.rc files are "
                    "counted." << endl;
      return 0;
     }
    
     // Base directory
     CString sBaseDir(argv[1]);
    
     // Recursive flag
     CString s(argv[2]);
     s.MakeUpper();
     bool bRecursive=(s=="-R");
     
     // Extensions
     int  nExtStart=2;
     
     if(bRecursive) nExtStart++;
    
     // Extensions buffer
     CArray pExts; 
     
     if(nExtStart>=argc){
      
      // Fill extensions buffer with predefined extensions
      FillExts(pExts, pPredefinedExts);
     }
     else {
      
      // Get extensions from command line
      FillExts(pExts, argv+nExtStart);
     }
    
     SCAN_INFO ScanInfo;
    
     // Start loop for folders from base dir
     FoldersLoop(sBaseDir, pExts, bRecursive, ScanInfo);
    
     pExts.RemoveAll();
    
     // Ouput all statistics accumulated
     cout << endl 
          << "Total lines : " << ScanInfo.lLines << endl
          << "Comments : " << ScanInfo.lComments 
          << " (" << (int)(100.0*ScanInfo.lComments/ScanInfo.lLines) 
          << "%)" << endl
          << "Headers  : " << ScanInfo.lHeaders 
          << " (" << (int)(100.0*ScanInfo.lHeaders/ScanInfo.lLines) 
          << "%)" << endl
          << "Code  : " << ScanInfo.lCode 
          << " (" << (int)(100.0*ScanInfo.lCode/ScanInfo.lLines) 
          << "%)" << endl
          << "Resources : " << ScanInfo.lResources 
          << " (" << (int)(100.0*ScanInfo.lResources/ScanInfo.lLines) 
          << "%)" << endl;
     
     return 0;
    }
    

    Downloads

    Download source - 3 Kb

    IT Offers


    Top Authors