2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS project statistics
5 * PURPOSE: Main program file
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/01-2002 Created
14 typedef struct _EXTENSION_INFO
16 struct _EXTENSION_INFO
* Next
;
17 struct _FILE_INFO
* StatInfoList
;
19 TCHAR ExpandedExtName
[128];
21 TCHAR Description
[256];
25 } EXTENSION_INFO
, *PEXTENSION_INFO
;
27 typedef struct _FILE_INFO
29 struct _FILE_INFO
* Next
;
30 struct _FILE_INFO
* StatInfoListNext
;
31 PEXTENSION_INFO ExtInfo
;
32 TCHAR FileName
[MAX_PATH
];
36 } FILE_INFO
, *PFILE_INFO
;
39 PEXTENSION_INFO ExtInfoList
;
40 PFILE_INFO StatInfoList
;
41 BOOLEAN SkipEmptyLines
, BeSilent
;
44 TCHAR
*Options
[MAX_OPTIONS
];
58 PEXTENSION_INFO ExtInfo
;
59 PEXTENSION_INFO NextExtInfo
;
61 ExtInfo
= ExtInfoList
;
62 while (ExtInfo
!= NULL
)
64 NextExtInfo
= ExtInfo
->Next
;
65 HeapFree (GetProcessHeap(), 0, ExtInfo
);
66 ExtInfo
= NextExtInfo
;
72 AddExtension(LPTSTR ExtName
,
75 PEXTENSION_INFO ExtInfo
;
80 ExtInfo
= (PEXTENSION_INFO
) HeapAlloc (GetProcessHeap(), 0, sizeof (EXTENSION_INFO
));
84 for(t
= ExtName
; *t
!= _T('\0'); t
+= _tcslen(t
) + 1);
85 ln
= (DWORD
)t
- (DWORD
)ExtName
;
87 ZeroMemory (ExtInfo
, sizeof (EXTENSION_INFO
));
88 memcpy (ExtInfo
->ExtName
, ExtName
, ln
);
89 _tcscpy (ExtInfo
->Description
, Description
);
91 for(t
= ExtInfo
->ExtName
; *t
!= _T('\0'); t
+= _tcslen(t
) + 1)
93 if(ExtInfo
->nExtensions
++ != 0)
94 _tcscat (ExtInfo
->ExpandedExtName
, _T(";"));
95 _tcscat (ExtInfo
->ExpandedExtName
, _T("*."));
96 _tcscat (ExtInfo
->ExpandedExtName
, t
);
102 while (Info
->Next
!= NULL
)
106 Info
->Next
= ExtInfo
;
110 ExtInfoList
= ExtInfo
;
118 AddFile(LPTSTR FileName
,
119 PEXTENSION_INFO ExtInfo
)
124 StatInfo
= (PFILE_INFO
) HeapAlloc (GetProcessHeap(), 0, sizeof (FILE_INFO
));
127 ZeroMemory (StatInfo
, sizeof (FILE_INFO
));
128 _tcscpy (StatInfo
->FileName
, FileName
);
129 StatInfo
->ExtInfo
= ExtInfo
;
131 if (ExtInfo
->StatInfoList
)
133 Info
= ExtInfo
->StatInfoList
;
134 while (Info
->StatInfoListNext
!= NULL
)
136 Info
= Info
->StatInfoListNext
;
138 Info
->StatInfoListNext
= StatInfo
;
142 ExtInfo
->StatInfoList
= StatInfo
;
148 while (Info
->Next
!= NULL
)
152 Info
->Next
= StatInfo
;
156 StatInfoList
= StatInfo
;
164 CleanupAfterFile(VOID
)
166 if(FileHandle
!= INVALID_HANDLE_VALUE
)
167 CloseHandle (FileHandle
);
172 LoadFile(LPTSTR FileName
)
176 FileHandle
= CreateFile (FileName
, // Create this file
177 GENERIC_READ
, // Open for reading
180 OPEN_EXISTING
, // Open the file
181 FILE_ATTRIBUTE_NORMAL
, // Normal file
182 NULL
); // No attribute template
183 if (FileHandle
== INVALID_HANDLE_VALUE
)
186 FileSize
= GetFileSize (FileHandle
, NULL
);
189 CloseHandle (FileHandle
);
198 ReadLines(PFILE_INFO StatInfo
)
200 DWORD ReadBytes
, LineLen
;
201 static char FileBuffer
[1024];
202 char LastChar
= '\0';
206 while(ReadFile (FileHandle
, FileBuffer
, sizeof(FileBuffer
), &ReadBytes
, NULL
) && ReadBytes
>= sizeof(char))
208 for(Current
= FileBuffer
; ReadBytes
> 0; ReadBytes
-= sizeof(char), Current
++)
210 if(*Current
== '\n' && LastChar
== '\r')
213 if(!SkipEmptyLines
|| (LineLen
> 0))
214 StatInfo
->LineCount
++;
216 StatInfo
->EmptyLines
++;
221 if(SkipEmptyLines
&& (*Current
== ' ' || *Current
== '\t'))
230 StatInfo
->LineCount
+= (LineLen
> 0);
231 StatInfo
->EmptyLines
+= ((LastChar
!= '\0') && (LineLen
== 0));
236 PrintStatistics(VOID
)
238 PEXTENSION_INFO Info
;
239 DWORD TotalFileCount
;
240 DWORD TotalLineCount
;
242 DWORD TotalEmptyLines
;
249 for (Info
= ExtInfoList
; Info
!= NULL
; Info
= Info
->Next
)
251 TotalFileCount
+= Info
->FileCount
;
252 TotalLineCount
+= Info
->LineCount
;
253 TotalEmptyLines
+= Info
->EmptyLines
;
256 TotalAvgLF
= (TotalFileCount
? TotalLineCount
/ TotalFileCount
: 0);
258 for (Info
= ExtInfoList
; Info
!= NULL
; Info
= Info
->Next
)
262 if (Info
->FileCount
!= 0)
264 AvgLF
= (Info
->FileCount
? Info
->LineCount
/ Info
->FileCount
: 0);
272 _tprintf (_T("File extension%c : %s\n"), ((Info
->nExtensions
> 1) ? _T('s') : _T(' ')), Info
->ExpandedExtName
);
273 _tprintf (_T("File ext. description : %s\n"), Info
->Description
);
274 _tprintf (_T("Number of files : %lu\n"), Info
->FileCount
);
275 _tprintf (_T("Number of lines : %lu\n"), Info
->LineCount
);
277 _tprintf (_T("Number of empty lines : %lu\n"), Info
->EmptyLines
);
278 _tprintf (_T("Proportion of lines : %.2f %%\n"), (float)(TotalLineCount
? (((float)Info
->LineCount
* 100) / (float)TotalLineCount
) : 0));
279 _tprintf (_T("Average no. lines/file : %lu\n"), AvgLF
);
283 _tprintf (_T("Total number of files : %lu\n"), TotalFileCount
);
284 _tprintf (_T("Total number of lines : %lu\n"), TotalLineCount
);
286 _tprintf (_T("Total number of empty lines : %lu\n"), TotalEmptyLines
);
287 _tprintf (_T("Average no. lines/file : %lu\n"), TotalAvgLF
);
292 ProcessFiles(LPTSTR Path
)
294 WIN32_FIND_DATA FindFile
;
295 PEXTENSION_INFO Info
;
296 TCHAR SearchPath
[256];
308 ZeroMemory (&FindFile
, sizeof (FindFile
));
309 _tcscpy (SearchPath
, Path
);
310 _tcscat (SearchPath
, _T("\\*."));
311 _tcscat (SearchPath
, Ext
);
312 _tcscpy (FindFile
.cFileName
, SearchPath
);
313 SearchHandle
= FindFirstFile (SearchPath
, &FindFile
);
314 if (SearchHandle
!= INVALID_HANDLE_VALUE
)
319 if (!(FindFile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
321 _tcscpy (FileName
, Path
);
322 _tcscat (FileName
, _T("\\"));
323 _tcscat (FileName
, FindFile
.cFileName
);
325 if (LoadFile (FileName
))
329 StatInfo
= AddFile (FindFile
.cFileName
, Info
);
332 _tprintf (_T("Not enough free memory.\n"));
336 ReadLines (StatInfo
);
339 Info
->LineCount
+= StatInfo
->LineCount
;
340 Info
->EmptyLines
+= StatInfo
->EmptyLines
;
345 More
= FindNextFile (SearchHandle
, &FindFile
);
347 FindClose (SearchHandle
);
349 Ext
+= _tcslen(Ext
) + 1;
350 } while(*Ext
!= _T('\0'));
358 ProcessDirectories(LPTSTR Path
)
360 WIN32_FIND_DATA FindFile
;
361 TCHAR SearchPath
[MAX_PATH
];
367 _tprintf (_T("Processing %s ...\n"), Path
);
370 _tcscpy (SearchPath
, Path
);
371 _tcscat (SearchPath
, _T("\\*.*"));
373 SearchHandle
= FindFirstFileEx (SearchPath
,
376 FindExSearchLimitToDirectories
,
379 if (SearchHandle
!= INVALID_HANDLE_VALUE
)
384 if ((FindFile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
385 && (_tcscmp (FindFile
.cFileName
, _T(".")) != 0)
386 && (_tcscmp (FindFile
.cFileName
, _T("..")) != 0)
387 && (_tcscmp (FindFile
.cFileName
, _T("CVS")) != 0))
389 _tcscpy (SearchPath
, Path
);
390 _tcscat (SearchPath
, _T("\\"));
391 _tcscat (SearchPath
, FindFile
.cFileName
);
392 if (!ProcessDirectories (SearchPath
))
394 if (!ProcessFiles (SearchPath
))
397 More
= FindNextFile (SearchHandle
, &FindFile
);
399 FindClose (SearchHandle
);
410 _tprintf (_T("No extensions specified.\n"));
414 if (!ProcessDirectories (Path
))
416 _tprintf (_T("Failed to process directories.\n"));
420 if (!ProcessFiles (Path
))
422 _tprintf (_T("Failed to process files.\n"));
430 IsOptionSet(TCHAR
*Option
)
433 for(i
= 0; i
< MAX_OPTIONS
; i
++)
438 if(!_tcscmp(Options
[i
], Option
))
446 main (int argc
, char * argv
[])
450 TCHAR Path
[MAX_PATH
+ 1];
453 _tprintf (_T("ReactOS Project Statistics\n"));
454 _tprintf (_T("==========================\n\n"));
456 if (argc
< 2 || argc
> 2 + MAX_OPTIONS
)
458 _tprintf(_T("Usage: stats [-e] [-s] directory\n"));
459 _tprintf(_T(" -e: don't count empty lines\n"));
460 _tprintf(_T(" -s: be silent, don't print directories while processing\n"));
465 AddExtension (_T("c\0\0"), _T("Ansi C Source files"));
466 AddExtension (_T("cpp\0cxx\0\0"), _T("C++ Source files"));
467 AddExtension (_T("h\0\0"), _T("Header files"));
469 for(a
= 1; a
< argc
- 1; a
++)
472 int len
= lstrlenA(argv
[a
]);
473 TCHAR
*str
= (TCHAR
*)HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(TCHAR
));
474 if(MultiByteToWideChar(CP_ACP
, 0, argv
[a
], -1, str
, len
+ 1) > 0)
475 Options
[a
- 1] = str
;
477 Options
[a
- 1] = NULL
;
479 Options
[a
- 1] = argv
[a
];
483 SkipEmptyLines
= IsOptionSet(_T("-e"));
484 BeSilent
= IsOptionSet(_T("-s"));
487 ZeroMemory(Path
, sizeof(Path
));
488 if(MultiByteToWideChar(CP_ACP
, 0, argv
[argc
- 1], -1, Path
, MAX_PATH
) > 0)
491 Execute (argv
[argc
- 1]);