LOCNESS

LOCness is my take on a line of code counter.  Most code counters I've seen searches for certain tokens such as the semicolon and just counts those.  I decided to take it a step further by doing a basic intepretation of the code. -- in other words, I try to identify classes, functions, variables, and constructs.  Luckily, I have some experience in that kind of parsing when I did my interpreter, so I took code from that project, stripped it down, adjust it for reading C++.

The utility is fairly straightforward.  To begin, a project configuration must be created.  Once a base project path is specified, files from that path and its subdirectories can be included in the count by selecting and adding them to the list of project files.  The main window is shown on the right -- not very fancy, but it does the job of establishing a list of files to report on which is the truly main feature of the program.

The left side windows serves as a file  explorer:  The top-left window displays the folder hierarchy from the project base path.  When a folder is selected, the bottom-left window displays the files in that path.  You can add all the files in the path at once or selectively choose them.  The right window shows the files that will be counted.  You can remove selected files from the list or clear the list entirely with a click of the button.  Note that removing the files from this list does not actually delete the files from storage.

locness.zip
Development version
Build Date: Feb, 2006 

 

There is also a "marking" directory where the program makes copies of the original source files and marks the lines that are actually counted.  The marked file can also display a "model" of the code which identifies relationships between classes, functions, and variables.  Here is a sample of a marked file:

-----------------------------------------------------------------------

LOCness Report

.\Stockyard.cpp

 

Classes: 1

Functions: 3

Variables: 9

Statements: 34

Directives: 8

 

Element Total: 55

Line Total: 50

 

Preprocessor:

  #include "stdafx.h"

  #include <windows .h >

  #include "psapi.h"

  #include "uiGlobals.h"

  #include "syServer.h"

  BEGIN_MESSAGE_MAPsyApp {105}CWinApp {104}

  ON_COMMANDID_HELP {105}CWinApp ::OnHelp {104}

  END_MESSAGE_MAP {104}

 

Code Model:

  Class: syApp [25]

     Funct: InitInstance  return: BOOL [25]

     Funct: ExitInstance  return: int [56]

     Funct: CheckAppInstance  return: bool [67]

-----------------------------------------------------------------------

  1 |/***********************************************************************

  2 |Stockyard.cpp

  3 |Merged startup class

  4 |***********************************************************************/

  5+|#include "stdafx.h"

  6+|#include <windows.h>

  7+|#include "psapi.h"

  8 |

  9+|#include "uiGlobals.h"

 10+|#include "syServer.h"

 11 |

 12+|extern syServer    SVR;

 13+|syApp APP;

 14 |

 15 |

 16 |/***********************************************************************

 17 |***********************************************************************/

 18+|BEGIN_MESSAGE_MAP(syApp, CWinApp)

 19+|   ON_COMMAND(ID_HELP, CWinApp::OnHelp)

 20+|END_MESSAGE_MAP()

 21 |

 22 |

 23 |/***********************************************************************

 24 |***********************************************************************/

 25+|BOOL syApp::InitInstance()

 26 |{

 27+|    if (!CheckAppInstance())

 28 |    {

 29 |        MessageBox(NULL, "Stockyard Process already exist.  Cannot Proceed.",

 30+|            "Critical Error", MB_OK);

 31+|        return FALSE;

 32 |    }

 33 |

 34+|    if(!AfxSocketInit())

 35 |    {

 36+|        TRACE("Stockyard: Failed to Initialize Sockets");

 37+|        return FALSE;

 38 |    }

 39 |

 40+|    HANDLE syProc = GetCurrentProcess();

 41+|    SetPriorityClass(syProc, ABOVE_NORMAL_PRIORITY_CLASS);

 42 |//    SetPriorityClass(syProc, REALTIME_PRIORITY_CLASS);

 43 |

 44 |    AfxBeginThread(RUNTIME_CLASS(syServer),

 45+|        THREAD_PRIORITY_NORMAL,0,0,NULL);

 46 |

 47+|    Sleep(500);

 48 |

 49+|    UI.CreateWnd();

 50+|    m_pMainWnd = &UI;

 51 |

 52+|    return TRUE;

 53 |}

 54 |

 55 |

 56+|int syApp::ExitInstance()

 57 |{

 58+|    UI.DestroyWnd();

 59+|    return 0;

 60 |}

 61 |

 62 |

 63 |/***********************************************************************

 64 |CheckAppInstance - Checks if an instance of the program is already

 65 |running

 66 |***********************************************************************/

 67+|bool syApp::CheckAppInstance()

 68 |{

 69 |/*  ...Get the list of process identifiers.

 70 |*/

 71+|    DWORD pArr[1024], retSize, count;

 72+|    HANDLE hProcess;

 73+|    HMODULE hMod;

 74+|    char pName[MAX_PATH];

 75+|    DWORD i;

 76 |

 77+|    DWORD syProcId = GetCurrentProcessId();

 78+|    if (!EnumProcesses(pArr, sizeof(pArr), &retSize ) )

 79+|        return false;

 80 |

 81+|    count = retSize / sizeof(DWORD);

 82+|    for (i=0;i<count;i++)

 83 |    {

 84+|        if (pArr[i] == syProcId)

 85+|            continue;

 86 |

 87 |        hProcess = OpenProcess(PROCESS_ALL_ACCESS |PROCESS_QUERY_INFORMATION,

 88+|            FALSE, pArr[i]);

 89 |

 90+|        if (!hProcess)

 91+|            continue;

 92 |

 93+|        if (EnumProcessModules(hProcess,&hMod,sizeof(hMod),&retSize))

 94 |        {

 95+|            GetModuleBaseName(hProcess, hMod, pName, sizeof(pName));

 96+|            if (!strcmp(pName,"StockyardSvr.exe"))

 97 |            {

 98+|                CloseHandle(hProcess);

 99+|                return false;

100 |            }

101 |       }

102 |

103+|       CloseHandle( hProcess );

104 |   }

105 |

106+|   return true;

107 |}

108 |

109 |

The marked file list two sets of counts: the first is the sum of all elements, and the second is the number of distinct lines.  An element can be a class, function, or variable definition/declaration, or even a statement or preprocessor directive.  Sometimes more than two elements can be found in a line (i.e. a variable initialization) which is why the two counts may not be the same.  Following the counts is the code model which shows a hierarchy of classes and functions.  Finally, the code is reprinted with line numbers then marked with an '+' if it was counted.

 Rules of Counting >>