diff --git a/reactos/apps/utils/stats/stats.c b/reactos/apps/utils/stats/stats.c index 521c6f3c3ed..21f78084ba1 100644 --- a/reactos/apps/utils/stats/stats.c +++ b/reactos/apps/utils/stats/stats.c @@ -21,6 +21,7 @@ typedef struct _EXTENSION_INFO TCHAR Description[256]; DWORD FileCount; DWORD LineCount; + DWORD EmptyLines; } EXTENSION_INFO, *PEXTENSION_INFO; typedef struct _FILE_INFO @@ -30,26 +31,29 @@ typedef struct _FILE_INFO PEXTENSION_INFO ExtInfo; TCHAR FileName[MAX_PATH]; DWORD LineCount; + DWORD EmptyLines; DWORD FunctionCount; } FILE_INFO, *PFILE_INFO; HANDLE FileHandle; -DWORD TotalLineCount; PEXTENSION_INFO ExtInfoList; PFILE_INFO StatInfoList; +BOOLEAN SkipEmptyLines; + +#define MAX_OPTIONS 1 +TCHAR *Options[MAX_OPTIONS]; VOID -Initialize() +Initialize(VOID) { - TotalLineCount = 0; ExtInfoList = NULL; StatInfoList = NULL; } VOID -Cleanup() +Cleanup(VOID) { PEXTENSION_INFO ExtInfo; PEXTENSION_INFO NextExtInfo; @@ -157,7 +161,7 @@ AddFile(LPTSTR FileName, VOID -CleanupAfterFile() +CleanupAfterFile(VOID) { if(FileHandle != INVALID_HANDLE_VALUE) CloseHandle (FileHandle); @@ -190,10 +194,10 @@ LoadFile(LPTSTR FileName) } -DWORD -ReadLines() +VOID +ReadLines(PFILE_INFO StatInfo) { - DWORD ReadBytes, LineLen, Lines = 0; + DWORD ReadBytes, LineLen; static char FileBuffer[1024]; char LastChar = '\0'; char *Current; @@ -201,51 +205,52 @@ ReadLines() LineLen = 0; while(ReadFile (FileHandle, FileBuffer, sizeof(FileBuffer), &ReadBytes, NULL) && ReadBytes >= sizeof(char)) { - if(ReadBytes & 0x1) - ReadBytes--; - for(Current = FileBuffer; ReadBytes > 0; ReadBytes -= sizeof(char), Current++) { if(*Current == '\n' && LastChar == '\r') { LastChar = '\0'; - if(LineLen > 0) - Lines++; + if(!SkipEmptyLines || (LineLen > 0)) + StatInfo->LineCount++; + if(LineLen == 0) + StatInfo->EmptyLines++; LineLen = 0; + continue; } - LineLen++; LastChar = *Current; + if(SkipEmptyLines && (*Current == ' ' || *Current == '\t')) + { + continue; + } + if(*Current != '\r') + LineLen++; } } - Lines += (LineLen > 0); - return Lines; + StatInfo->LineCount += (LineLen > 0); + StatInfo->EmptyLines += ((LastChar != '\0') && (LineLen == 0)); } VOID -DoStatisticsForFile(PFILE_INFO StatInfo) -{ - StatInfo->LineCount = ReadLines(); -} - - -VOID -PrintStatistics() +PrintStatistics(VOID) { PEXTENSION_INFO Info; DWORD TotalFileCount; DWORD TotalLineCount; DWORD TotalAvgLF; + DWORD TotalEmptyLines; TotalFileCount = 0; TotalLineCount = 0; + TotalEmptyLines = 0; Info = ExtInfoList; for (Info = ExtInfoList; Info != NULL; Info = Info->Next) { TotalFileCount += Info->FileCount; TotalLineCount += Info->LineCount; + TotalEmptyLines += Info->EmptyLines; } TotalAvgLF = (TotalFileCount ? TotalLineCount / TotalFileCount : 0); @@ -264,18 +269,22 @@ PrintStatistics() } _tprintf (_T("\n")); - _tprintf (_T("File extension%c : %s\n"), ((Info->nExtensions > 1) ? _T('s') : _T(' ')), Info->ExpandedExtName); - _tprintf (_T("File ext. description : %s\n"), Info->Description); - _tprintf (_T("Number of files : %lu\n"), Info->FileCount); - _tprintf (_T("Number of lines : %lu\n"), Info->LineCount); - _tprintf (_T("Proportion of lines : %.2f %%\n"), (float)(TotalLineCount ? (((float)Info->LineCount * 100) / (float)TotalLineCount) : 0)); - _tprintf (_T("Average no. lines/file : %lu\n"), AvgLF); + _tprintf (_T("File extension%c : %s\n"), ((Info->nExtensions > 1) ? _T('s') : _T(' ')), Info->ExpandedExtName); + _tprintf (_T("File ext. description : %s\n"), Info->Description); + _tprintf (_T("Number of files : %lu\n"), Info->FileCount); + _tprintf (_T("Number of lines : %lu\n"), Info->LineCount); + if(SkipEmptyLines) + _tprintf (_T("Number of empty lines : %lu\n"), Info->EmptyLines); + _tprintf (_T("Proportion of lines : %.2f %%\n"), (float)(TotalLineCount ? (((float)Info->LineCount * 100) / (float)TotalLineCount) : 0)); + _tprintf (_T("Average no. lines/file : %lu\n"), AvgLF); } _tprintf (_T("\n")); - _tprintf (_T("Total number of files : %lu\n"), TotalFileCount); - _tprintf (_T("Total number of lines : %lu\n"), TotalLineCount); - _tprintf (_T("Average no. lines/file : %lu\n"), TotalAvgLF); + _tprintf (_T("Total number of files : %lu\n"), TotalFileCount); + _tprintf (_T("Total number of lines : %lu\n"), TotalLineCount); + if(SkipEmptyLines) + _tprintf (_T("Total number of empty lines : %lu\n"), TotalEmptyLines); + _tprintf (_T("Average no. lines/file : %lu\n"), TotalAvgLF); } @@ -324,10 +333,11 @@ ProcessFiles(LPTSTR Path) return FALSE; } - DoStatisticsForFile (StatInfo); + ReadLines (StatInfo); Info->FileCount++; Info->LineCount += StatInfo->LineCount; + Info->EmptyLines += StatInfo->EmptyLines; CleanupAfterFile(); } @@ -413,19 +423,36 @@ Execute(LPTSTR Path) PrintStatistics(); } +BOOLEAN +IsOptionSet(TCHAR *Option) +{ + int i; + for(i = 0; i < MAX_OPTIONS; i++) + { + if(!Options[i]) + continue; + + if(!_tcscmp(Options[i], Option)) + return TRUE; + } + return FALSE; +} + int main (int argc, char * argv []) { + int a; #if UNICODE TCHAR Path[MAX_PATH + 1]; #endif _tprintf (_T("\nReactOS project statistics generator.\n\n")); - if (argc < 2) + if (argc < 2 || argc > 2 + MAX_OPTIONS) { - _tprintf(_T("Usage: stats directory")); + _tprintf(_T("Usage: stats [-e] directory\n")); + _tprintf(_T(" -e: don't count empty lines")); return 1; } @@ -433,12 +460,29 @@ main (int argc, char * argv []) AddExtension (_T("c\0\0"), _T("Ansi C Source files")); AddExtension (_T("cpp\0cxx\0\0"), _T("C++ Source files")); AddExtension (_T("h\0\0"), _T("Header files")); + + for(a = 1; a < argc - 1; a++) + { +#if UNICODE + int len = lstrlenA(argv[a]); + TCHAR *str = (TCHAR*)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(TCHAR)); + if(MultiByteToWideChar(CP_ACP, 0, argv[a], -1, str, len + 1) > 0) + Options[a - 1] = str; + else + Options[a - 1] = NULL; +#else + Options[a - 1] = argv[a]; +#endif + } + + SkipEmptyLines = IsOptionSet(_T("-e")); + #if UNICODE ZeroMemory(Path, sizeof(Path)); - if(MultiByteToWideChar(CP_ACP, 0, argv[1], -1, Path, MAX_PATH) > 0) + if(MultiByteToWideChar(CP_ACP, 0, argv[argc - 1], -1, Path, MAX_PATH) > 0) Execute (Path); #else - Execute (argv[1]); + Execute (argv[argc - 1]); #endif Cleanup();