Browse Source

Initial commit

master
Vladislav Glinsky 7 years ago
commit
4dab7093da
Signed by: cl0ne GPG Key ID: 9D058DD29491782E
  1. 27
      .gitignore
  2. BIN
      Counting Rules/Counting_Standards_Ada.pdf
  3. BIN
      Counting Rules/Counting_Standards_Assembly.pdf
  4. BIN
      Counting Rules/Counting_Standards_Bash_Shell_Script.pdf
  5. BIN
      Counting Rules/Counting_Standards_CFScript.pdf
  6. BIN
      Counting Rules/Counting_Standards_COBOL.pdf
  7. BIN
      Counting Rules/Counting_Standards_C_Cpp.pdf
  8. BIN
      Counting Rules/Counting_Standards_C_Sharp.pdf
  9. BIN
      Counting Rules/Counting_Standards_C_Shell.pdf
  10. BIN
      Counting Rules/Counting_Standards_Cascading_Style_Sheets.pdf
  11. BIN
      Counting Rules/Counting_Standards_Cold_Fusion.pdf
  12. BIN
      Counting Rules/Counting_Standards_DOS_Batch.pdf
  13. BIN
      Counting Rules/Counting_Standards_Fortran.pdf
  14. BIN
      Counting Rules/Counting_Standards_HTML_XML.pdf
  15. BIN
      Counting Rules/Counting_Standards_IDL.pdf
  16. BIN
      Counting Rules/Counting_Standards_Java.pdf
  17. BIN
      Counting Rules/Counting_Standards_MATLAB.pdf
  18. BIN
      Counting Rules/Counting_Standards_Makefile.pdf
  19. BIN
      Counting Rules/Counting_Standards_ObjC.pdf
  20. BIN
      Counting Rules/Counting_Standards_PHP.pdf
  21. BIN
      Counting Rules/Counting_Standards_Pascal.pdf
  22. BIN
      Counting Rules/Counting_Standards_Perl.pdf
  23. BIN
      Counting Rules/Counting_Standards_Python.pdf
  24. BIN
      Counting Rules/Counting_Standards_Ruby.pdf
  25. BIN
      Counting Rules/Counting_Standards_SQL.pdf
  26. BIN
      Counting Rules/Counting_Standards_Scala.pdf
  27. BIN
      Counting Rules/Counting_Standards_VHDL.pdf
  28. BIN
      Counting Rules/Counting_Standards_Verilog.pdf
  29. BIN
      Counting Rules/Counting_Standards_Visual_Basic.pdf
  30. BIN
      Counting Rules/Counting_Standards_X-Midas.pdf
  31. BIN
      Counting Rules/Cyclomatic_Complexity_Standard.pdf
  32. 20
      Makefile
  33. 20
      Makefile_cygwin
  34. 13
      README.md
  35. 208
      UCC.2010.vcxproj
  36. 339
      UCC.2010.vcxproj.filters
  37. 22
      UCC.2015.sln
  38. 220
      UCC.2015.vcxproj
  39. 354
      UCC.2015.vcxproj.filters
  40. BIN
      UCC_release_notes_v.2018.07.pdf
  41. BIN
      UCC_user_manual_v.2018.07.pdf
  42. 40
      contributors.txt
  43. 69
      gui/GAsciiDialog.cpp
  44. 37
      gui/GAsciiDialog.h
  45. 100
      gui/GAsciiDialog.ui
  46. 384
      gui/GExtensionDialog.cpp
  47. 60
      gui/GExtensionDialog.h
  48. 235
      gui/GExtensionDialog.ui
  49. 32
      gui/GFileOpenMenu.cpp
  50. 32
      gui/GFileOpenMenu.h
  51. 50
      gui/GFileOpenMenu.ui
  52. 1898
      gui/GMainWindow.cpp
  53. 130
      gui/GMainWindow.h
  54. 1140
      gui/GMainWindow.ui
  55. 99
      gui/GSideBySideDialog.cpp
  56. 42
      gui/GSideBySideDialog.h
  57. 138
      gui/GTableDialog.cpp
  58. 37
      gui/GTableDialog.h
  59. 97
      gui/GTableDialog.ui
  60. BIN
      gui/GUCC.ico
  61. 2
      gui/GUCC.rc
  62. 42
      gui/GUtil.cpp
  63. 25
      gui/GUtil.h
  64. 25
      gui/Qt_main.cpp
  65. 60
      gui/UCCWorker.cpp
  66. 50
      gui/UCCWorker.h
  67. 189
      gui/gucc.pro
  68. 15
      gui/gucc.qrc
  69. BIN
      gui/images/add_folder.png
  70. BIN
      gui/images/arrow.png
  71. BIN
      gui/images/close.png
  72. BIN
      gui/images/edit.png
  73. BIN
      gui/images/gucc.icns
  74. BIN
      gui/images/gucc.png
  75. BIN
      gui/images/help.png
  76. BIN
      gui/images/minus_sign.png
  77. BIN
      gui/images/open.png
  78. BIN
      gui/images/plus_sign.png
  79. BIN
      gui/images/start.png
  80. BIN
      gui/images/stop.png
  81. 208
      license.txt
  82. 23
      src/BOOST_LICENSE_1_0.txt
  83. 783
      src/CAdaCounter.cpp
  84. 48
      src/CAdaCounter.h
  85. 299
      src/CAssemblyCounter.cpp
  86. 45
      src/CAssemblyCounter.h
  87. 947
      src/CBashCounter.cpp
  88. 55
      src/CBashCounter.h
  89. 904
      src/CBatchCounter.cpp
  90. 50
      src/CBatchCounter.h
  91. 306
      src/CCCounter.cpp
  92. 43
      src/CCCounter.h
  93. 661
      src/CCFScriptCounter.cpp
  94. 46
      src/CCFScriptCounter.h
  95. 1396
      src/CCJavaCsScalaCounter.cpp
  96. 67
      src/CCJavaCsScalaCounter.h
  97. 979
      src/CCobolCounter.cpp
  98. 50
      src/CCobolCounter.h
  99. 2840
      src/CCodeCounter.cpp
  100. 397
      src/CCodeCounter.h

27
.gitignore

@ -0,0 +1,27 @@
# common
.DS_Store
[Tt]humbs.db
[Dd]esktop.ini
*.bak
*~
.~*#
.directory
*.lnk
# build and user files
*.user
ipch/
*.opendb
*.opensdf
*.sdf
*.ncb
*.suo
*.log
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
[Bb]in/
[Oo]bj/
[Ll]og/
.vs/

BIN
Counting Rules/Counting_Standards_Ada.pdf

BIN
Counting Rules/Counting_Standards_Assembly.pdf

BIN
Counting Rules/Counting_Standards_Bash_Shell_Script.pdf

BIN
Counting Rules/Counting_Standards_CFScript.pdf

BIN
Counting Rules/Counting_Standards_COBOL.pdf

BIN
Counting Rules/Counting_Standards_C_Cpp.pdf

BIN
Counting Rules/Counting_Standards_C_Sharp.pdf

BIN
Counting Rules/Counting_Standards_C_Shell.pdf

BIN
Counting Rules/Counting_Standards_Cascading_Style_Sheets.pdf

BIN
Counting Rules/Counting_Standards_Cold_Fusion.pdf

BIN
Counting Rules/Counting_Standards_DOS_Batch.pdf

BIN
Counting Rules/Counting_Standards_Fortran.pdf

BIN
Counting Rules/Counting_Standards_HTML_XML.pdf

BIN
Counting Rules/Counting_Standards_IDL.pdf

BIN
Counting Rules/Counting_Standards_Java.pdf

BIN
Counting Rules/Counting_Standards_MATLAB.pdf

BIN
Counting Rules/Counting_Standards_Makefile.pdf

BIN
Counting Rules/Counting_Standards_ObjC.pdf

BIN
Counting Rules/Counting_Standards_PHP.pdf

BIN
Counting Rules/Counting_Standards_Pascal.pdf

BIN
Counting Rules/Counting_Standards_Perl.pdf

BIN
Counting Rules/Counting_Standards_Python.pdf

BIN
Counting Rules/Counting_Standards_Ruby.pdf

BIN
Counting Rules/Counting_Standards_SQL.pdf

BIN
Counting Rules/Counting_Standards_Scala.pdf

BIN
Counting Rules/Counting_Standards_VHDL.pdf

BIN
Counting Rules/Counting_Standards_Verilog.pdf

BIN
Counting Rules/Counting_Standards_Visual_Basic.pdf

BIN
Counting Rules/Counting_Standards_X-Midas.pdf

BIN
Counting Rules/Cyclomatic_Complexity_Standard.pdf

20
Makefile

@ -0,0 +1,20 @@
#UNAME := $(shell uname)
#ifeq ($(UNAME), SunOS)
all:
mkdir -p tmp
cp src/* tmp
for file in $(shell ls tmp) ; do \
sed -i -e 's///g' tmp/$$file ; \
done
mkdir -p bin
g++ -Wall -std=c++0x -o bin/UCC -DUNIX tmp/*.cpp
rm -rf tmp
#endif
#notSunOS:
#mkdir -p bin
#g++ -Wall -o bin/UCC -DUNIX src/*.cpp
clean:
-rm -f bin/UCC bin/UCC.exe
-rm -rf tmp
-rmdir bin

20
Makefile_cygwin

@ -0,0 +1,20 @@
#UNAME := $(shell uname)
#ifeq ($(UNAME), SunOS)
all:
mkdir -p tmp
cp src/* tmp
for file in $(shell ls tmp) ; do \
sed -i -e 's///g' tmp/$$file ; \
done
mkdir -p bin
g++ -Wall -o bin/UCC -DUNIX -DCYGWIN tmp/*.cpp
rm -rf tmp
#endif
#notSunOS:
#mkdir -p bin
#g++ -Wall -o bin/UCC -DUNIX src/*.cpp
clean:
-rm -f bin/UCC bin/UCC.exe
-rm -rf tmp
-rmdir bin

13
README.md

@ -0,0 +1,13 @@
# Unified Code Counter
The Unified Code Counter (UCC) is a comprehensive software lines of code counter produced by the USC Center for Systems and Software Engineering.
It is available to the general public as open source code and can be compiled with any ANSI standard C++ compiler.
**Homepage:** [http://csse.usc.edu/ucc_new/wordpress/](http://csse.usc.edu/ucc_new/wordpress/)
## Repository info
This repo contains a copy of latest released [version 2018.07](http://csse.usc.edu/ucc_new/wordpress/2018/07/26/ucc-version-2018-07/) sources:
> Finally! Our next, and last, UCC release! We have decided to focus on UCC-Java, so that it has all the features UCC currently does. Hence, I have decided to make this release available to everyone.
[Release notes](UCC_release_notes_v.2018.07.pdf), [user manual](UCC_user_manual_v.2018.07.pdf) are available as PDFs. Also you can find line count and cyclomatic complexity metric calculation rules in `Counting Rules` subdirectory.
The tool successfully compiles under Linux, yet it's somewhat buggy and doesn't provide complete support for modern languages' standards.

208
UCC.2010.vcxproj

@ -0,0 +1,208 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>UCC</ProjectName>
<ProjectGuid>{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">bin/Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">bin/Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<OutputFile>$(OutDir)UCC.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)UCC.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)UCC.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\CAdaCounter.cpp" />
<ClCompile Include="src\CAssemblyCounter.cpp" />
<ClCompile Include="src\CBashCounter.cpp" />
<ClCompile Include="src\CBatchCounter.cpp" />
<ClCompile Include="src\CCJavaCsScalaCounter.cpp" />
<ClCompile Include="src\CCobolCounter.cpp" />
<ClCompile Include="src\cc_main.cpp" />
<ClCompile Include="src\CCCounter.cpp" />
<ClCompile Include="src\CCFScriptCounter.cpp" />
<ClCompile Include="src\CCodeCounter.cpp" />
<ClCompile Include="src\CColdFusionCounter.cpp" />
<ClCompile Include="src\CCsharpCounter.cpp" />
<ClCompile Include="src\CCshCounter.cpp" />
<ClCompile Include="src\CCssCounter.cpp" />
<ClCompile Include="src\CDataCounter.cpp" />
<ClCompile Include="src\CFortranCounter.cpp" />
<ClCompile Include="src\CHtmlCounter.cpp" />
<ClCompile Include="src\CIdlCounter.cpp" />
<ClCompile Include="src\CJavaCounter.cpp" />
<ClCompile Include="src\CJavascriptCounter.cpp" />
<ClCompile Include="src\CMakefileCounter.cpp" />
<ClCompile Include="src\CMatlabCounter.cpp" />
<ClCompile Include="src\CMidasCounter.cpp" />
<ClCompile Include="src\CmpMngr.cpp" />
<ClCompile Include="src\CmpMngrHtml.cpp" />
<ClCompile Include="src\CNeXtMidasCounter.cpp" />
<ClCompile Include="src\CObjCCounter.cpp" />
<ClCompile Include="src\CPascalCounter.cpp" />
<ClCompile Include="src\CPerlCounter.cpp" />
<ClCompile Include="src\CPhpCounter.cpp" />
<ClCompile Include="src\CPythonCounter.cpp" />
<ClCompile Include="src\CRubyCounter.cpp" />
<ClCompile Include="src\CScalaCounter.cpp" />
<ClCompile Include="src\CSqlCounter.cpp" />
<ClCompile Include="src\CTagCounter.cpp" />
<ClCompile Include="src\CUtil.cpp" />
<ClCompile Include="src\CVbCounter.cpp" />
<ClCompile Include="src\CVbscriptCounter.cpp" />
<ClCompile Include="src\CVerilogCounter.cpp" />
<ClCompile Include="src\CVHDLCounter.cpp" />
<ClCompile Include="src\CWebCounter.cpp" />
<ClCompile Include="src\CXMidasCounter.cpp" />
<ClCompile Include="src\CXmlCounter.cpp" />
<ClCompile Include="src\DiffTool.cpp" />
<ClCompile Include="src\FunctionParser.cpp" />
<ClCompile Include="src\LangUtils.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\MainObject.cpp" />
<ClCompile Include="src\UCCExceptDump.cpp" />
<ClCompile Include="src\UCCFilesOut.cpp" />
<ClCompile Include="src\UCCGlobals.cpp" />
<ClCompile Include="src\UCCThread.cpp" />
<ClCompile Include="src\UserIF.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CAdaCounter.h" />
<ClInclude Include="src\CAssemblyCounter.h" />
<ClInclude Include="src\CBashCounter.h" />
<ClInclude Include="src\CBatchCounter.h" />
<ClInclude Include="src\CCJavaCsScalaCounter.h" />
<ClInclude Include="src\CCobolCounter.h" />
<ClInclude Include="src\cc_main.h" />
<ClInclude Include="src\CCCounter.h" />
<ClInclude Include="src\CCFScriptCounter.h" />
<ClInclude Include="src\CCJavaCsCounter.h" />
<ClInclude Include="src\CCodeCounter.h" />
<ClInclude Include="src\CColdFusionCounter.h" />
<ClInclude Include="src\CCsharpCounter.h" />
<ClInclude Include="src\CCshCounter.h" />
<ClInclude Include="src\CCssCounter.h" />
<ClInclude Include="src\CDataCounter.h" />
<ClInclude Include="src\CFortranCounter.h" />
<ClInclude Include="src\CHtmlCounter.h" />
<ClInclude Include="src\CIdlCounter.h" />
<ClInclude Include="src\CJavaCounter.h" />
<ClInclude Include="src\CJavascriptCounter.h" />
<ClInclude Include="src\CMakefileCounter.h" />
<ClInclude Include="src\CMatlabCounter.h" />
<ClInclude Include="src\CMidasCounter.h" />
<ClInclude Include="src\CmpMngr.h" />
<ClInclude Include="src\CmpMngrHtml.h" />
<ClInclude Include="src\CNeXtMidasCounter.h" />
<ClInclude Include="src\CObjCCounter.h" />
<ClInclude Include="src\CPascalCounter.h" />
<ClInclude Include="src\CPerlCounter.h" />
<ClInclude Include="src\CPhpCounter.h" />
<ClInclude Include="src\CPythonCounter.h" />
<ClInclude Include="src\CRubyCounter.h" />
<ClInclude Include="src\CScalaCounter.h" />
<ClInclude Include="src\CSqlCounter.h" />
<ClInclude Include="src\CTagCounter.h" />
<ClInclude Include="src\CUtil.h" />
<ClInclude Include="src\CVbCounter.h" />
<ClInclude Include="src\CVbscriptCounter.h" />
<ClInclude Include="src\CVerilogCounter.h" />
<ClInclude Include="src\CVHDLCounter.h" />
<ClInclude Include="src\CWebCounter.h" />
<ClInclude Include="src\CXMidasCounter.h" />
<ClInclude Include="src\CXmlCounter.h" />
<ClInclude Include="src\DiffTool.h" />
<ClCompile Include="src\FunctionParser.h" />
<ClInclude Include="src\LangUtils.h" />
<ClInclude Include="src\MainObject.h" />
<ClInclude Include="src\UCCExceptDump.h" />
<ClInclude Include="src\UCCFilesOut.h" />
<ClInclude Include="src\UCCGlobals.h" />
<ClInclude Include="src\UCCThread.h" />
<ClInclude Include="src\UserIF.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

339
UCC.2010.vcxproj.filters

@ -0,0 +1,339 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CAdaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CBashCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\cc_main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCFScriptCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCodeCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CColdFusionCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCsharpCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCshCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCssCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CDataCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CFortranCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CHtmlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CJavaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CJavascriptCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CMakefileCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CMatlabCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CMidasCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CmpMngr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CNeXtMidasCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CObjCCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPascalCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPerlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPhpCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPythonCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CRubyCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CSqlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CTagCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVbCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVbscriptCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVerilogCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVHDLCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CWebCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CXMidasCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CXmlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\DiffTool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\MainObject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UserIF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CAssemblyCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CBatchCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCJavaCsScalaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCobolCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CIdlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CmpMngrHtml.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CScalaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\LangUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCExceptDump.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCFilesOut.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCGlobals.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\FunctionParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CAdaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CBashCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\cc_main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCFScriptCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCJavaCsCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCodeCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CColdFusionCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCsharpCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCshCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCssCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CDataCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CFortranCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CHtmlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CJavaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CJavascriptCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CMakefileCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CMatlabCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CMidasCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CmpMngr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CNeXtMidasCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CObjCCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPascalCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPerlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPhpCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPythonCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CRubyCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CSqlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CTagCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CUtil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVbCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVbscriptCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVerilogCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVHDLCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CWebCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CXMidasCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CXmlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\DiffTool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\MainObject.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UserIF.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CAssemblyCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CBatchCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCJavaCsScalaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCobolCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CIdlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CmpMngrHtml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CScalaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\LangUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCExceptDump.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCFilesOut.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCGlobals.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCThread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClCompile Include="src\FunctionParser.h">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

22
UCC.2015.sln

@ -0,0 +1,22 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UCC", "UCC.2015.vcxproj", "{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}.Debug|x86.ActiveCfg = Debug|Win32
{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}.Debug|x86.Build.0 = Debug|Win32
{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}.Release|x86.ActiveCfg = Release|Win32
{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

220
UCC.2015.vcxproj

@ -0,0 +1,220 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>UCC</ProjectName>
<ProjectGuid>{FA47D54A-CAC6-4A69-B2CB-F3C4F9C37B0B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">bin/Debug\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">bin/Release\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<TargetName>UCC</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
<Link>
<OutputFile>$(OutDir)UCC.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)UCC.pdb</ProgramDatabaseFile>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<OutputFile>$(OutDir)UCC.exe</OutputFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\CAdaCounter.cpp" />
<ClCompile Include="src\CAssemblyCounter.cpp" />
<ClCompile Include="src\CBashCounter.cpp" />
<ClCompile Include="src\CBatchCounter.cpp" />
<ClCompile Include="src\CCJavaCsScalaCounter.cpp" />
<ClCompile Include="src\CCobolCounter.cpp" />
<ClCompile Include="src\cc_main.cpp" />
<ClCompile Include="src\CCCounter.cpp" />
<ClCompile Include="src\CCFScriptCounter.cpp" />
<ClCompile Include="src\CCodeCounter.cpp" />
<ClCompile Include="src\CColdFusionCounter.cpp" />
<ClCompile Include="src\CCsharpCounter.cpp" />
<ClCompile Include="src\CCshCounter.cpp" />
<ClCompile Include="src\CCssCounter.cpp" />
<ClCompile Include="src\CDataCounter.cpp" />
<ClCompile Include="src\CFortranCounter.cpp" />
<ClCompile Include="src\CHtmlCounter.cpp" />
<ClCompile Include="src\CIdlCounter.cpp" />
<ClCompile Include="src\CJavaCounter.cpp" />
<ClCompile Include="src\CJavascriptCounter.cpp" />
<ClCompile Include="src\CMakefileCounter.cpp" />
<ClCompile Include="src\CMatlabCounter.cpp" />
<ClCompile Include="src\CMidasCounter.cpp" />
<ClCompile Include="src\CmpMngr.cpp" />
<ClCompile Include="src\CmpMngrHtml.cpp" />
<ClCompile Include="src\CNeXtMidasCounter.cpp" />
<ClCompile Include="src\CObjCCounter.cpp" />
<ClCompile Include="src\CPascalCounter.cpp" />
<ClCompile Include="src\CPerlCounter.cpp" />
<ClCompile Include="src\CPhpCounter.cpp" />
<ClCompile Include="src\CPythonCounter.cpp" />
<ClCompile Include="src\CRubyCounter.cpp" />
<ClCompile Include="src\CScalaCounter.cpp" />
<ClCompile Include="src\CSqlCounter.cpp" />
<ClCompile Include="src\CTagCounter.cpp" />
<ClCompile Include="src\CUtil.cpp" />
<ClCompile Include="src\CVbCounter.cpp" />
<ClCompile Include="src\CVbscriptCounter.cpp" />
<ClCompile Include="src\CVerilogCounter.cpp" />
<ClCompile Include="src\CVHDLCounter.cpp" />
<ClCompile Include="src\CWebCounter.cpp" />
<ClCompile Include="src\CXMidasCounter.cpp" />
<ClCompile Include="src\CXmlCounter.cpp" />
<ClCompile Include="src\DiffTool.cpp" />
<ClCompile Include="src\FunctionParser.cpp" />
<ClCompile Include="src\LangUtils.cpp" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\MainObject.cpp" />
<ClCompile Include="src\UCCExceptDump.cpp" />
<ClCompile Include="src\UCCFilesOut.cpp" />
<ClCompile Include="src\UCCGlobals.cpp" />
<ClCompile Include="src\UCCThread.cpp" />
<ClCompile Include="src\UserIF.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CAdaCounter.h" />
<ClInclude Include="src\CAssemblyCounter.h" />
<ClInclude Include="src\CBashCounter.h" />
<ClInclude Include="src\CBatchCounter.h" />
<ClInclude Include="src\CCJavaCsScalaCounter.h" />
<ClInclude Include="src\CCobolCounter.h" />
<ClInclude Include="src\cc_main.h" />
<ClInclude Include="src\CCCounter.h" />
<ClInclude Include="src\CCFScriptCounter.h" />
<ClInclude Include="src\CCJavaCsCounter.h" />
<ClInclude Include="src\CCodeCounter.h" />
<ClInclude Include="src\CColdFusionCounter.h" />
<ClInclude Include="src\CCsharpCounter.h" />
<ClInclude Include="src\CCshCounter.h" />
<ClInclude Include="src\CCssCounter.h" />
<ClInclude Include="src\CDataCounter.h" />
<ClInclude Include="src\CFortranCounter.h" />
<ClInclude Include="src\CHtmlCounter.h" />
<ClInclude Include="src\CIdlCounter.h" />
<ClInclude Include="src\CJavaCounter.h" />
<ClInclude Include="src\CJavascriptCounter.h" />
<ClInclude Include="src\CMakefileCounter.h" />
<ClInclude Include="src\CMatlabCounter.h" />
<ClInclude Include="src\CMidasCounter.h" />
<ClInclude Include="src\CmpMngr.h" />
<ClInclude Include="src\CmpMngrHtml.h" />
<ClInclude Include="src\CNeXtMidasCounter.h" />
<ClInclude Include="src\CObjCCounter.h" />
<ClInclude Include="src\CPascalCounter.h" />
<ClInclude Include="src\CPerlCounter.h" />
<ClInclude Include="src\CPhpCounter.h" />
<ClInclude Include="src\CPythonCounter.h" />
<ClInclude Include="src\CRubyCounter.h" />
<ClInclude Include="src\CScalaCounter.h" />
<ClInclude Include="src\CSqlCounter.h" />
<ClInclude Include="src\CTagCounter.h" />
<ClInclude Include="src\CUtil.h" />
<ClInclude Include="src\CVbCounter.h" />
<ClInclude Include="src\CVbscriptCounter.h" />
<ClInclude Include="src\CVerilogCounter.h" />
<ClInclude Include="src\CVHDLCounter.h" />
<ClInclude Include="src\CWebCounter.h" />
<ClInclude Include="src\CXMidasCounter.h" />
<ClInclude Include="src\CXmlCounter.h" />
<ClInclude Include="src\DiffTool.h" />
<ClInclude Include="src\FunctionParser.h" />
<ClInclude Include="src\LangUtils.h" />
<ClInclude Include="src\MainObject.h" />
<ClInclude Include="src\sema.h" />
<ClInclude Include="src\UCCAfterLibraryIncludes.h" />
<ClInclude Include="src\UCCBeforeLibraryIncludes.h" />
<ClInclude Include="src\UCCExceptDump.h" />
<ClInclude Include="src\UCCFilesOut.h" />
<ClInclude Include="src\UCCGlobals.h" />
<ClInclude Include="src\UCCThread.h" />
<ClInclude Include="src\UserIF.h" />
</ItemGroup>
<ItemGroup>
<Text Include="src\BOOST_LICENSE_1_0.txt" />
</ItemGroup>
<ItemGroup>
<None Include="src\sema_h_LICENSE" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

354
UCC.2015.vcxproj.filters

@ -0,0 +1,354 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\CAdaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CBashCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\cc_main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCFScriptCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCodeCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CColdFusionCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCsharpCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCshCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCssCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CDataCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CFortranCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CHtmlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CJavaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CJavascriptCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CMakefileCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CMatlabCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CMidasCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CmpMngr.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CNeXtMidasCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPascalCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPerlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPhpCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CPythonCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CRubyCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CSqlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CTagCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CUtil.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVbCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVbscriptCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVerilogCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CVHDLCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CWebCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CXMidasCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CXmlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\DiffTool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\MainObject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UserIF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CBatchCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CmpMngrHtml.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCJavaCsScalaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCFilesOut.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCGlobals.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\LangUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCThread.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CAssemblyCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CCobolCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CIdlCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CScalaCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\UCCExceptDump.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\CObjCCounter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\FunctionParser.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\CAdaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CBashCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\cc_main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCFScriptCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCJavaCsCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCodeCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CColdFusionCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCsharpCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCshCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCssCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CDataCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CFortranCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CHtmlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CJavaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CJavascriptCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CMakefileCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CMatlabCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CMidasCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CmpMngr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CNeXtMidasCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPascalCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPerlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPhpCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CPythonCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CRubyCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CSqlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CTagCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CUtil.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVbCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVbscriptCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVerilogCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CVHDLCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CWebCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CXMidasCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CXmlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\DiffTool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\MainObject.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UserIF.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CBatchCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CmpMngrHtml.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCJavaCsScalaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCFilesOut.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCGlobals.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="src\LangUtils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCThread.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CAssemblyCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CCobolCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CIdlCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CScalaCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCExceptDump.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\CObjCCounter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\sema.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCAfterLibraryIncludes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\UCCBeforeLibraryIncludes.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\FunctionParser.h">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Text Include="src\BOOST_LICENSE_1_0.txt" />
</ItemGroup>
<ItemGroup>
<None Include="src\sema_h_LICENSE" />
</ItemGroup>
</Project>

BIN
UCC_release_notes_v.2018.07.pdf

BIN
UCC_user_manual_v.2018.07.pdf

40
contributors.txt

@ -0,0 +1,40 @@
Below is the list of major contributors listed in anti-chronological order.
Dr. Barry Boehm, Marilee Wheaton, and A Winsor Brown had the idea of creating a tool that would provide a standard for code counting, which led to UCC.
All UCC versions:
* University of Southern California CSCI 590 with Center for Systems and Software Engineering DR students that worked on the UCC project have contributed significantly, and are all greatly appreciated for their high-quality work, dedication, desire to learn, and motivation to improve UCC as a product.
* The Aerospace Corporation and Integrated Applications Incorporated, thank you for your IV&V efforts!
2009 - Present
* Marilyn A. Sperka, thank you for being a valuable member of the UCC team, training everyone on the team, answering questions, and providing valuable insight.
2014 - Present
* Randy Maxwell, thank you for making major performance improvements to UCC, modifying the algorithms to consume less RAM, implementing the Scala parser, and implementing UCC to be multithreaded! Additionally, for your independent testing and helping CSCI 590 students implement and fix defects.
2017
* Paul Cymerman and Joseph VanDyke, thank you for the suggestions for improvement and implementing the initial Maintainability Index output option!
2009 - 2014
* Ryan Pfeifer, thank you for your major contributions for making UCC the product it is today!
2013.04
* Robert Christensen, thank you for making a major modification and performance improvement to the Differencing algorithm!
2011.10
* Shunpike Baba, thank you for contributing a defect fix!
2009 - 2011
* Joni Kim, thank you for your extensive testing and quality assurance efforts!
2000 - 2011
* Vu Nguyen, thank you for your major contributions for making UCC the product it is today, and managing the USC students!
2008-2009
* Mike Lee, thank you for leading the early UCC project efforts!
2002
* Paul Cymerman, Betsy Legg, and Sarah Capellari for coding up the first Diff Tool add-on to UCC!

69
gui/GAsciiDialog.cpp

@ -0,0 +1,69 @@
//! GAsciiDialog class methods.
/*!
* \file GAsciiDialog.cpp
*
* This file contains the GAsciiDialog class methods.
*/
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include "GAsciiDialog.h"
/*!
* Constructs a GAsciiDialog object.
*
* \param filePath results file or directory
* \param parent parent widget
* \param f window flags
*/
GAsciiDialog::GAsciiDialog(const QString &filePath, QWidget *parent, Qt::WindowFlags f)
: QDialog(parent, f)
{
ui.setupUi(this);
outputDir = "";
ui.cboResultsSelect->clear();
ui.txtResults->clear();
QFont font = ui.txtResults->font();
font.setStyleHint(QFont::Monospace);
font.setFamily("Courier");
ui.txtResults->setFont(font);
if (!filePath.isEmpty())
{
QFileInfo fi(filePath);
if (fi.isDir())
{
outputDir = filePath;
QDir dir(filePath);
dir.setNameFilters(QStringList() << tr("*outfile*.txt") << tr("MatchedPairs.txt") << tr("*DuplicatePairs.txt") << tr("error_log_*.txt"));
QStringList fileList = dir.entryList();
for (int i = 0; i < fileList.count(); i++)
ui.cboResultsSelect->addItem(fileList.at(i));
}
else if (fi.isFile())
{
outputDir = fi.absolutePath();
ui.cboResultsSelect->addItem(fi.fileName());
}
}
}
/*!
* Selects a file to display.
*
* \param fileName file name
*/
void GAsciiDialog::on_cboResultsSelect_currentIndexChanged(const QString &fileName)
{
ui.txtResults->clear();
QFile file(outputDir + "/" + fileName);
if (file.open(QIODevice::ReadOnly))
{
QString text = file.readAll();
file.close();
ui.txtResults->setText(text);
}
}

37
gui/GAsciiDialog.h

@ -0,0 +1,37 @@
//! GAsciiDialog class definitions.
/*!
* \file GAsciiDialog.h
*
* This file contains the GAsciiDialog class definition.
*/
#ifndef GASCIIDIALOG_H
#define GASCIIDIALOG_H
#include <QDialog>
#include "ui_GAsciiDialog.h"
//! ASCII dialog.
/*!
* \class GAsciiDialog
*
* Defines an ASCII dialog.
*/
class GAsciiDialog : public QDialog
{
Q_OBJECT
public:
GAsciiDialog(const QString &filePath, QWidget *parent = 0, Qt::WindowFlags f = 0);
~GAsciiDialog(){};
private slots:
void on_cboResultsSelect_currentIndexChanged(const QString &fileName);
private:
Ui::GAsciiDialogClass ui;
QString outputDir; //!< Output directory defined by filePath
};
#endif // GASCIIDIALOG_H

100
gui/GAsciiDialog.ui

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GAsciiDialogClass</class>
<widget class="QDialog" name="GAsciiDialogClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>UCC Results</string>
</property>
<property name="windowIcon">
<iconset resource="gucc.qrc">
<normaloff>:/images/gucc.png</normaloff>:/images/gucc.png</iconset>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="cboResultsSelect"/>
</item>
<item>
<widget class="QTextEdit" name="txtResults">
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="gucc.qrc"/>
</resources>
<connections>
<connection>
<sender>btnClose</sender>
<signal>clicked()</signal>
<receiver>GAsciiDialogClass</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>418</x>
<y>482</y>
</hint>
<hint type="destinationlabel">
<x>510</x>
<y>470</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>closeWindow()</slot>
</slots>
</ui>

384
gui/GExtensionDialog.cpp

@ -0,0 +1,384 @@
//! GExtensionDialog class methods.
/*!
* \file GExtensionDialog.cpp
*
* This file contains the GExtensionDialog class methods.
*/
#include <QFile>
#include <QInputDialog>
#include <QMenu>
#include <QMessageBox>
#include "GExtensionDialog.h"
#include <QFileDialog> //Modification: 2018.04
#include "QFileInfo" //Modification: 2018.04
#include "GMainWindow.h" //Modification: 2018.04
/*!
* Constructs a GExtensionDialog object.
*
* \param extensionMapDefault map of default language extensions
* \param extensionMapCustom map of custom language extensions
* \param parent parent widget
* \param f window flags
*/
GExtensionDialog::GExtensionDialog(QMap<QString, QStringList *> *extensionMapDefault, QMap<QString, QStringList *> *extensionMapCustom,
QWidget *parent, Qt::WindowFlags f)
: QDialog(parent, f)
{
ui.setupUi(this);
extMapDefault = extensionMapDefault;
extMapCustom = extensionMapCustom;
customChanged = false;
extChanged = false;
QListWidgetItem *lwItem;
QFont font;
foreach (QString name, extMapDefault->keys())
{
ui.lwLanguages->addItem(name);
if (extMapCustom->contains(name))
{
lwItem = ui.lwLanguages->item(ui.lwLanguages->count() - 1);
font = lwItem->font();
font.setBold(true);
lwItem->setFont(font);
}
}
//Modification: 2018.04 Integration changes
bool flag = ((GMainWindow*)parent)->checkButtonClicked;
if(flag){
ui.pushButton_2->hide();
}
ui.tblExtensions->horizontalHeader()->setStretchLastSection(true);
connect(ui.lwLanguages, SIGNAL(itemClicked(QListWidgetItem *)), this, SLOT(languageSelected(QListWidgetItem *)));
connect(ui.tblExtensions, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(itemCustomContextMenuRequested(const QPoint &)));
}
/*!
* Destroys a GExtensionDialog object.
*/
GExtensionDialog::~GExtensionDialog()
{
}
/*!
* Updates list of extensions when a language is selected.
*
* \param lwItem selected list item
*/
void GExtensionDialog::languageSelected(QListWidgetItem *lwItem)
{
if (lwItem)
{
if (extChanged)
{
this->updateCustomExtensions();
extChanged = false;
}
QTableWidgetItem *tblItem;
//QStringList *extList; warning
QStringList *extList=NULL;
QString selLang = lwItem->text();
int i, cnt = 0;
for (i = ui.tblExtensions->rowCount() - 1; i >= 0; i--)
delete(ui.tblExtensions->takeItem(i, 0));
if (extMapCustom->contains(selLang))
extList = extMapCustom->value(selLang, 0);
else if (extMapDefault->contains(selLang))
extList = extMapDefault->value(selLang, 0);
ui.tblExtensions->setRowCount(extList->count());
if (extList->count() > 0)
{
for (i = 0; i < extList->count(); i++)
{
if (!extList->at(i).isEmpty())
{
tblItem = new QTableWidgetItem(extList->at(cnt));
tblItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
ui.tblExtensions->setItem(cnt, 0, tblItem);
cnt++;
}
}
}
}
}
/*!
* Updates list of custom extensions.
*/
void GExtensionDialog::updateCustomExtensions()
{
if (extChanged)
{
QList<QListWidgetItem *> lwItems = ui.lwLanguages->selectedItems();
QListWidgetItem *lwItem;
QStringList *extList;
QString selLang;
int i;
if (lwItems.count() > 0)
{
lwItem = lwItems.first();
selLang = lwItem->text();
if (extMapCustom->contains(selLang))
extList = extMapCustom->value(selLang);
else
{
extList = new QStringList();
extMapCustom->insert(selLang, extList);
}
extList->clear();
for (i = 0; i < ui.tblExtensions->rowCount(); i++)
extList->append(ui.tblExtensions->item(i, 0)->text());
}
extChanged = false;
}
}
/*!
* Loads a custom context menu for the extension table.
*
* \param pos location of mouse selection
*/
void GExtensionDialog::itemCustomContextMenuRequested(const QPoint &pos)
{
QMenu menu;
QAction *aItem = 0;
aItem = menu.addAction("Revert Selected Language Extensions", this, SLOT(revertSelLangExt()));
aItem = menu.addAction("Revert All Language Extensions", this, SLOT(revertAllLangExt()));
menu.exec(this->mapToGlobal(pos));
//Warning fix 11.25.16
(void)aItem;
}
/*!
* Reverts list of custom extensions to defaults for selected language.
*/
void GExtensionDialog::revertSelLangExt()
{
QList<QListWidgetItem *> lwItems = ui.lwLanguages->selectedItems();
QListWidgetItem *lwItem;
QFont font;
QStringList *extList;
QString langName;
if (lwItems.count() < 1)
return;
lwItem = lwItems.first();
langName = lwItem->text();
if (extMapCustom->contains(langName))
{
font = lwItem->font();
font.setBold(false);
lwItem->setFont(font);
extList = extMapCustom->value(langName);
delete(extList);
extMapCustom->remove(langName);
customChanged = true;
extChanged = false;
this->languageSelected(lwItem);
}
}
/*!
* Reverts all custom extensions to defaults.
*/
void GExtensionDialog::revertAllLangExt()
{
QList<QListWidgetItem *> lwItems = ui.lwLanguages->selectedItems();
QListWidgetItem *lwItem;
QFont font;
QList<QStringList *> extLists;
int i;
if (extMapCustom->count() < 1)
return;
for (i = 0; i < ui.lwLanguages->count(); i++)
{
lwItem = ui.lwLanguages->item(i);
font = lwItem->font();
font.setBold(false);
lwItem->setFont(font);
}
extLists = extMapCustom->values();
for (i = extLists.count() - 1; i >= 0; i--)
delete(extLists.takeAt(i));
extMapCustom->clear();
if (lwItems.count() > 0)
{
lwItem = lwItems.first();
this->languageSelected(lwItem);
}
customChanged = true;
extChanged = false;
}
/*!
* Adds a new extension to the list.
*/
void GExtensionDialog::on_btnAddExt_clicked()
{
QList<QTableWidgetItem *> tblItems = ui.tblExtensions->selectedItems();
QList<QListWidgetItem *> lwItems = ui.lwLanguages->selectedItems();
QTableWidgetItem *tblItem;
QListWidgetItem *lwItem;
QFont font;
QString ext;
int i, row;
bool ok;
if (lwItems.count() < 1)
{
QMessageBox::warning(this, tr("Add Error"), tr("Unable to add an extension without a selected language."));
return;
}
lwItem = lwItems.first();
ext = QInputDialog::getText(this, tr("Add Extension"), tr("Please enter an extension for %1").arg(lwItem->text()),
QLineEdit::Normal, "", &ok);
if (ok && !ext.isEmpty())
{
if (!ext.startsWith("."))
{
QMessageBox::warning(this, tr("Add Error"), tr("Unable to add extension for %1. Extension must begin with a '.' character."));
return;
}
for (i = 0; i < ui.tblExtensions->rowCount(); i++)
{
if (ui.tblExtensions->item(i, 0)->text() == ext)
break;
}
if (i < ui.tblExtensions->rowCount())
{
QMessageBox::warning(this, tr("Add Error"), tr("Unable to add extension for %1. Extension already exists."));
return;
}
if (tblItems.count() > 0)
{
tblItem = tblItems.first();
row = tblItem->row() + 1;
}
else
row = ui.tblExtensions->rowCount();
ui.tblExtensions->insertRow(row);
tblItem = new QTableWidgetItem(ext);
tblItem->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
ui.tblExtensions->setItem(row, 0, tblItem);
font = lwItem->font();
font.setBold(true);
lwItem->setFont(font);
customChanged = true;
extChanged = true;
this->updateCustomExtensions();
extChanged = false;
}
}
/*!
* Removes the selected extension(s).
*/
void GExtensionDialog::on_btnRemoveExt_clicked()
{
QList<QTableWidgetItem *> tblItems = ui.tblExtensions->selectedItems();
QList<QListWidgetItem *> lwItems = ui.lwLanguages->selectedItems();
QListWidgetItem *lwItem;
QFont font;
int i, row;
if (lwItems.count() < 1 || tblItems.count() < 1)
return;
lwItem = lwItems.first();
font = lwItem->font();
font.setBold(true);
lwItem->setFont(font);
for (i = 0; i < tblItems.count(); i++)
{
row = tblItems.at(i)->row();
delete(ui.tblExtensions->takeItem(row, 0));
ui.tblExtensions->removeRow(row);
customChanged = true;
extChanged = true;
this->updateCustomExtensions();
extChanged = false;
}
}
/*!
* Closes the dialog
*/
void GExtensionDialog::on_btnClose_clicked()
{
this->close();
}
/*!
* Processes a close event sent to the form.
*/
void GExtensionDialog::closeEvent(QCloseEvent *)
{
if (customChanged)
{
((GMainWindow*)(parent()))->writeExtensionsFile();
customChanged = false;
this->accept();
}
else
this->reject();
}
//Modification: 2018.04 USC starts
void GExtensionDialog::on_pushButton_clicked()
{
if (customChanged)
{
((GMainWindow*)(parent()))->writeExtensionsFile();
customChanged = false;
this->accept();
}
else
this->reject();
}
void GExtensionDialog::on_pushButton_2_clicked()
{
QString extensionFile="extensions.txt";
extensionFile = QFileDialog::getSaveFileName(this,
tr("Extension File"), extensionFile, tr("Extension File (*.txt)"), 0, QFileDialog::DontConfirmOverwrite);
if(extensionFile == "")
return;
QFileInfo fi(extensionFile);
if (!fi.exists())
{QFile file(extensionFile);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QMessageBox::warning(this, tr("File Error"), tr("Unable to open extension file: ") + extensionFile + "\n" + file.errorString() );
return;
}
file.close();
((GMainWindow*)(parent()))->ui.txtExtensionFile->setText(extensionFile);
}
this->close();
}
//Modification: 2018.04 USC ends

60
gui/GExtensionDialog.h

@ -0,0 +1,60 @@
//! GExtensionDialog class definitions.
/*!
* \file GExtensionDialog.h
*
* This file contains the GExtensionDialog class definition.
*/
#ifndef GEXTENSIONDIALOG_H
#define GEXTENSIONDIALOG_H
#include <QCloseEvent>
#include <QDialog>
#include "ui_GExtensionDialog.h"
#include "ui_GMainWindow.h" //Modification: 2018.04
//! Extension dialog.
/*!
* \class GExtensionDialog
*
* Defines an extension dialog.
*/
class GExtensionDialog : public QDialog
{
Q_OBJECT
public:
GExtensionDialog(QMap<QString, QStringList *> *extensionMapDefault, QMap<QString, QStringList *> *extensionMapCustom,
QWidget *parent = 0, Qt::WindowFlags f = 0);
~GExtensionDialog();
signals:
void updateExtensions();
private slots:
void languageSelected(QListWidgetItem *lwItem);
void itemCustomContextMenuRequested(const QPoint &pos);
void revertSelLangExt();
void revertAllLangExt();
void on_btnAddExt_clicked();
void on_btnRemoveExt_clicked();
void on_btnClose_clicked();
void closeEvent(QCloseEvent *);
void on_pushButton_clicked(); //Modification: 2018.04
void on_pushButton_2_clicked(); //Modification: 2018.04
private:
Ui::GExtensionDialogClass ui; //Modification: 2018.04
Ui::GMainWindowClass ui_main; //Modification: 2018.04
bool checkButtonClick; //Modification: 2018.04
QMap<QString, QStringList *> *extMapDefault; //!< Default extension map pointer
QMap<QString, QStringList *> *extMapCustom; //!< Custom extension map pointer
bool customChanged; //!< Flag indicating that custom extensions have changed
bool extChanged; //!< Flag indicating that unsaved extensions have changed for the current language
void updateCustomExtensions();
};
#endif // GEXTENSIONDIALOG_H

235
gui/GExtensionDialog.ui

@ -0,0 +1,235 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GExtensionDialogClass</class>
<widget class="QDialog" name="GExtensionDialogClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>389</height>
</rect>
</property>
<property name="windowTitle">
<string>Language File Extensions</string>
</property>
<property name="windowIcon">
<iconset resource="gucc.qrc">
<normaloff>:/images/gucc.png</normaloff>:/images/gucc.png</iconset>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="lblLanguages">
<property name="text">
<string>Languages:</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="lwLanguages"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget1">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="lblExtensions">
<property name="text">
<string>Extensions:</string>
</property>
</widget>
</item>
<item>
<widget class="QTableWidget" name="tblExtensions">
<property name="contextMenuPolicy">
<enum>Qt::CustomContextMenu</enum>
</property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="columnCount">
<number>1</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Extensions</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnAddExt">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Add language extension.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="gucc.qrc">
<normaloff>:/images/plus_sign.png</normaloff>:/images/plus_sign.png</iconset>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnRemoveExt">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Remove language extension(s).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="gucc.qrc">
<normaloff>:/images/minus_sign.png</normaloff>:/images/minus_sign.png</iconset>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnClose">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Close dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="gucc.qrc">
<normaloff>:/images/close.png</normaloff>:/images/close.png</iconset>
</property>
<property name="iconSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Save As</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="gucc.qrc"/>
</resources>
<connections/>
</ui>

32
gui/GFileOpenMenu.cpp

@ -0,0 +1,32 @@
//! GFileOpenMenu class methods.
/*!
* \file GFileOpenMenu.cpp
*
* This file contains the GFileOpenMenu class methods.
*/
#include <QFileDialog>
#include "GFileOpenMenu.h"
/*!
* Constructs a GFileOpenMenu object.
*
* \param parent parent widget
* \param f window flags
*/
GFileOpenMenu::GFileOpenMenu(QWidget *parent, Qt::WindowFlags f)
: QDialog(parent, f)
{
ui.setupUi(this);
ui.txtFileLines->clear();
QString qs = QFileDialog::getOpenFileName(this, tr("Add a file"), "", tr("All Files (*.*)"));
QFile file(qs);
if (file.open(QIODevice::ReadOnly))
{
QString text = file.readAll();
file.close();
ui.txtFileLines->setText(text);
}
}

32
gui/GFileOpenMenu.h

@ -0,0 +1,32 @@
//! GFileOpenMenu class definitions.
/*!
* \file GFileOpenMenu.h
*
* This file contains the GFileOpenMenu class definition.
*/
#ifndef GFILEOPENMENU_H
#define GFILEOPENMENU_H
#include <QDialog>
#include "ui_GFileOpenMenu.h"
//! File open menu dialog.
/*!
* \class GFileOpenMenu
*
* Defines a file open menu dialog.
*/
class GFileOpenMenu : public QDialog
{
Q_OBJECT
public:
GFileOpenMenu(QWidget *parent = 0, Qt::WindowFlags f = 0);
~GFileOpenMenu(){};
private:
Ui::GFileOpenMenuClass ui;
};
#endif // GFILEOPENMENU_H

50
gui/GFileOpenMenu.ui

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GFileOpenMenuClass</class>
<widget class="QDialog" name="GFileOpenMenuClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Open File</string>
</property>
<property name="windowIcon">
<iconset resource="gucc.qrc">
<normaloff>:/images/gucc.png</normaloff>:/images/gucc.png</iconset>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>781</width>
<height>581</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="txtFileLines"/>
</item>
<item>
<widget class="QDialogButtonBox" name="btnBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources>
<include location="gucc.qrc"/>
</resources>
<connections/>
</ui>

1898
gui/GMainWindow.cpp
File diff suppressed because it is too large
View File

130
gui/GMainWindow.h

@ -0,0 +1,130 @@
//! GMainWindow class definitions.
/*!
* \file GMainWindow.h
*
* This file contains the GMainWindow class definition.
*/
#ifndef GMAINWINDOW_H
#define GMAINWINDOW_H
#include <QList>
#include <QListWidgetItem>
#include <QMainWindow>
#include <QDropEvent>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QMap>
#include <QModelIndexList>
#include <QProgressBar>
#include "GAsciiDialog.h"
#include "GExtensionDialog.h"
#include "GTableDialog.h"
#include "ui_GMainWindow.h"
#define FILE_LIST_A "fileListA.txt"
#define FILE_LIST_B "fileListB.txt"
class GSideBySideDialog;
//! Main window.
/*!
* \class GMainWindow
*
* Defines a main window.
*/
class GMainWindow : public QMainWindow
{
Q_OBJECT
public:
GMainWindow(QWidget *parent = 0, Qt::WindowFlags f = 0);
~GMainWindow();
//Modification: 2018.04 starts
Ui::GMainWindowClass ui;
bool checkButtonClicked;
bool writeExtensionsFile();
//Modification: 2018.04 ends
signals:
void canceledExecution();
public slots:
void updateLog(const QString &err);
void updateProgress(const QString &msg, int pct);
private slots:
void on_btnStart_clicked();
void on_btnStop_clicked();
void on_actionOpen_File_triggered();
void on_actionEdit_Extensions_triggered();
void on_actionExit_triggered();
void on_actionUser_Manual_triggered();
void on_actionRelease_Notes_triggered();
void on_actionLicense_triggered();
void on_actionAbout_triggered();
void on_btnAddFileA_clicked();
void on_btnAddFileB_clicked();
void on_btnRemoveFileA_clicked();
void on_btnRemoveFileB_clicked();
void on_btnAddFolderA_clicked();
void on_btnAddFolderB_clicked();
void listACustomContextMenuRequested(const QPoint &pos);
void listBCustomContextMenuRequested(const QPoint &pos);
void removeAllFilesA();
void removeAllFilesB();
void on_btnClearSelExt_clicked();
void on_chkDifferencing_clicked();
void on_chkModThreshold_clicked();
void on_chkDupThreshold_clicked();
void on_chkTruncThreshold_clicked();
void on_btnBrowseOutputDir_clicked();
void on_chkExtensionFile_clicked();
void on_chooseExisting(); //Modification: 2018.04
void on_createNewFile_clicked(); //Modification : 2018.04
void on_btnBrowseExtensionFile_clicked();
void on_chkRamLimit_clicked();
void on_chkThreads_clicked();
QStringList getFilters();
void on_btnCustomHeader_clicked();
void on_cbxNoHeader_clicked();
void on_txtHeader_textChanged(const QString &arg1);
void on_txtHeader_editingFinished();
private:
//Ui::GMainWindowClass ui; //Modification: 2018.04
GExtensionDialog *extensionDialog;
GAsciiDialog *mAsciiDialog;
GTableDialog *mTableDialog;
QButtonGroup bgrpOutputFormat;
QProgressBar *progressBar;
//Qwebviewer
GSideBySideDialog *mSideBySideDialog;
QMap<QString, QStringList *> extensionMapDefault; //!< Map of default language extensions
QMap<QString, QStringList *> extensionMapCustom; //!< Map of custom language extensions
bool customChanged; //!< Flag indicating that custom extensions have changed
bool defaultDirSet; //!< Flag indicating that a file browser has been opened
bool execCanceled; //!< Flag indicating canceled execution
void executionRunning(bool enabled);
void getDefaultExtensions();
void extensionsUpdated();
bool parseExtensionsFile();
//bool writeExtensionsFile(); //Modification: 2018.04
bool parsePreferencesFile();
bool writePreferencesFile();
protected:
void dropEvent(QDropEvent *ev);
void dragEnterEvent(QDragEnterEvent *ev);
};
#endif // GMAINWINDOW_H

1140
gui/GMainWindow.ui
File diff suppressed because it is too large
View File

99
gui/GSideBySideDialog.cpp

@ -0,0 +1,99 @@
//! GSideBySideDialog class methods.
/*!
* \file GSideBySideDialog.cpp
*
* This file contains the GSideBySideDialog class methods.
*/
/* Modification: 2016.01; USC
Updated to no longer require UI file, needed for dynamic
webkit vs webengine code */
#ifndef NO_WEB_SUPPORT
#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFile>
#include "GSideBySideDialog.h"
//Different version of Qt need different web classes
#ifdef NEED_WEBKIT_LEGACY
#if (QT_VERSION < 0x050000)
#include <QWebView>
#else
#include <QtWebKitWidgets/QWebView>
#endif
#else
#include <QtWebEngineWidgets/QWebEngineView>
#endif
/*!
* Constructs a GSideBySideDialog object.
*
* \param filePathA souce A file or directory
* \param filePathB souce B file or directory
* \param parent parent widget
*/
GSideBySideDialog::GSideBySideDialog(const QString &filePathA, const QString &filePathB,
const QString &htmlPath, QWidget *parent)
:QDialog(parent)
{
//Create the child widgets
QLineEdit *lineEdit = new QLineEdit(this);
QLineEdit *lineEdit_2 = new QLineEdit(this);
QPushButton *btnClose = new QPushButton(this);
btnClose->setText("Close");
connect(btnClose, SIGNAL(clicked()), this, SLOT(accept()));
#ifdef NEED_WEBKIT_LEGACY
QWebView *webView = new QWebView(this);
#else
QWebEngineView *webView = new QWebEngineView(this);
#endif
//layout the child widgets in this window
QVBoxLayout *masterVLayout = new QVBoxLayout();
QHBoxLayout *editLayout = new QHBoxLayout();
editLayout->addWidget(lineEdit);
editLayout->addWidget(lineEdit_2);
editLayout->setContentsMargins(0,0,0,0);
QHBoxLayout *closeLayout = new QHBoxLayout();
closeLayout->addStretch();
closeLayout->addWidget(btnClose);
closeLayout->addStretch();
closeLayout->setContentsMargins(0,0,0,0);
masterVLayout->addLayout(editLayout);
masterVLayout->addWidget(webView);
masterVLayout->addLayout(closeLayout);
masterVLayout->setContentsMargins(0,0,0,0);
this->setLayout(masterVLayout);
this->setWindowTitle("UCC Differencing Side-by-side Results");
this->resize(811, 497);
//Initialize data from the passed in arguments
if (!filePathA.isEmpty())
{
lineEdit->setText(filePathA);
lineEdit->setEnabled(true);
}
if (!filePathB.isEmpty())
{
lineEdit_2->setText(filePathB);
lineEdit_2->setEnabled(true);
}
QString filename = htmlPath + "/" + HTML_FILE;
if (QFile(filename).exists())
{
webView->load(QUrl::fromLocalFile(filename));
}
else
{
qDebug() << "WARNING: " << filename << " does not exist!";
}
}
#endif

42
gui/GSideBySideDialog.h

@ -0,0 +1,42 @@
//! GSideBySideDialog class definitions.
/*!
* \file GSideBySideDialog.h
*
* This file contains the GSideBySideDialog class definition.
*/
#ifndef GSIDEBYSIDEDIALOG_H
#define GSIDEBYSIDEDIALOG_H
#ifndef NO_WEB_SUPPORT
#include <QDialog>
/* Modification: 2016.01; USC
Updated to no longer require UI file, needed for dynamic
webkit vs webengine code */
#define HTML_FILE "highlighted_diff.html"
//! Sidebyside dialog.
/*!
* \class GSideBySideDialog
*
* Defines an Sidebyside dialog.
*/
namespace Ui {
class GSideBySideDialog;
}
class GSideBySideDialog : public QDialog
{
Q_OBJECT
public:
/* Modification: 2016.01; USC
Minor cosmetic updates */
GSideBySideDialog(const QString &filePathA, const QString &filePathB,
const QString &htmlPath, QWidget *parent = 0);
};
#endif
#endif // GSIDEBYSIDEDIALOG_H

138
gui/GTableDialog.cpp

@ -0,0 +1,138 @@
//! GAsciiDialog class methods.
/*!
* \file GAsciiDialog.cpp
*
* This file contains the GAsciiDialog class methods.
*/
#include <QDir>
#include <QTextStream>
#include "GTableDialog.h"
/*!
* Constructs a GTableDialog object.
*
* \param filePath results file or directory
* \param parent parent widget
* \param f window flags
*/
GTableDialog::GTableDialog(const QString &filePath, QWidget *parent, Qt::WindowFlags f)
: QDialog(parent, f)
{
ui.setupUi(this);
outputDir = "";
ui.cboResultsSelect->clear();
ui.tblResults->clear();
if (!filePath.isEmpty())
{
QFileInfo fi(filePath);
if (fi.isDir())
{
outputDir = filePath;
QDir dir(filePath);
dir.setNameFilters(QStringList() << tr("*outfile*.csv") << tr("MatchedPairs.csv") << tr("*DuplicatePairs.csv"));
QStringList fileList = dir.entryList();
for (int i = 0; i < fileList.count(); i++)
ui.cboResultsSelect->addItem(fileList.at(i));
}
else if (fi.isFile())
{
outputDir = fi.absolutePath();
ui.cboResultsSelect->addItem(fi.fileName());
}
}
}
/*!
* Selects a file to display.
*
* \param fileName file name
*/
void GTableDialog::on_cboResultsSelect_currentIndexChanged(const QString &fileName)
{
ui.tblResults->clear();
ui.tblResults->setColumnCount(0);
ui.tblResults->setRowCount(0);
QFile file(outputDir + "/" + fileName);
if (file.open(QIODevice::ReadOnly))
{
QTextStream ts(&file);
QTableWidgetItem *twItem;
QString line;
int i = -1, j, k, n;
while (ts.status() == QTextStream::Ok && !ts.atEnd())
{
line = ts.readLine();
if (!line.isEmpty())
{
i++;
ui.tblResults->insertRow(i);
QStringList s;
/*
* In some cases, we want to display quotes or commas in CSV file.
* To do that, we need to quote the whole line.
* In this if condition, we parse this kind of text and display it in one column
*/
if (line.at(0) == QChar('"') && line.endsWith(QChar('"')))
{
line = line.mid(1, line.size() - 2);
QString temp = "";
for (int it1 = 0; it1 < line.size(); it1++)
{
temp.append(line.at(it1));
/*
* The quote character we want to display in CSV has been replace with two quote characters ("")
* So here we need to skip one quote character
*/
if (line.at(it1) == QChar('"') && it1 + 1 < line.size() && line.at(it1 + 1) == QChar('"'))
it1++;
}
s.append(temp);
}
else s = line.split(',');
if (s.count() > ui.tblResults->columnCount())
ui.tblResults->setColumnCount(s.count());
for (j = 0; j < s.count(); j++)
{
twItem = new QTableWidgetItem(s.value(j));
ui.tblResults->setItem(i, j, twItem);
if (s.value(j).length() > 15 && j == s.count() - 1)
ui.tblResults->setSpan(i, j, 1, 2);
else if (j < s.count() - 1 && s.value(j + 1).isEmpty())
{
n = 2;
for (k = j + 1; k < s.count() - 1; k++)
{
if (!s.value(k + 1).isEmpty())
break;
n++;
}
ui.tblResults->setSpan(i, j, 1, n);
}
}
}
}
// update span for title rows
for (i = 0; i < ui.tblResults->rowCount() - 1; i++)
{
QString text = ui.tblResults->item(i, 0)->text();
if (ui.tblResults->item(i, 0)->text().startsWith(" "))
{
for (j = 0; j < ui.tblResults->columnCount(); j++)
{
if (!ui.tblResults->item(i + 1, j) || ui.tblResults->item(i + 1, j)->text().isEmpty())
break;
n = ui.tblResults->columnSpan(i + 1, j);
if (n > 1)
j += n - 1;
}
if (j < ui.tblResults->columnCount())
ui.tblResults->setSpan(i, 0, 1, j);
}
}
}
}

37
gui/GTableDialog.h

@ -0,0 +1,37 @@
//! GTableDialog class definitions.
/*!
* \file GTableDialog.h
*
* This file contains the GTableDialog class definition.
*/
#ifndef GTABLEDIALOG_H
#define GTABLEDIALOG_H
#include <QDialog>
#include "ui_GTableDialog.h"
//! Table dialog.
/*!
* \class GTableDialog
*
* Defines a table dialog.
*/
class GTableDialog : public QDialog
{
Q_OBJECT
public:
GTableDialog(const QString &filePath, QWidget *parent = 0, Qt::WindowFlags f = 0);
~GTableDialog(){};
private slots:
void on_cboResultsSelect_currentIndexChanged(const QString &fileName);
private:
Ui::GTableDialogClass ui;
QString outputDir; //!< Output directory defined by filePath
};
#endif // GTABLEDIALOG_H

97
gui/GTableDialog.ui

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GTableDialogClass</class>
<widget class="QDialog" name="GTableDialogClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>500</height>
</rect>
</property>
<property name="windowTitle">
<string>UCC Results</string>
</property>
<property name="windowIcon">
<iconset resource="gucc.qrc">
<normaloff>:/images/gucc.png</normaloff>:/images/gucc.png</iconset>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QComboBox" name="cboResultsSelect"/>
</item>
<item>
<widget class="QTableWidget" name="tblResults">
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="btnClose">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="gucc.qrc"/>
</resources>
<connections>
<connection>
<sender>btnClose</sender>
<signal>clicked()</signal>
<receiver>GTableDialogClass</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>430</x>
<y>476</y>
</hint>
<hint type="destinationlabel">
<x>506</x>
<y>469</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>closeWin()</slot>
</slots>
</ui>

BIN
gui/GUCC.ico

2
gui/GUCC.rc

@ -0,0 +1,2 @@
IDI_ICON1 ICON DISCARDABLE "gucc.ico"

42
gui/GUtil.cpp

@ -0,0 +1,42 @@
//! GUtil class static methods.
/*!
* \file GUtil.h
*
* This file contains the GUtil class static methods.
*/
#include <QProcess>
#include "GUtil.h"
/*!
* Opens the specified file using the default application.
*
* \param filePath file path to open
*
* \return status
*/
bool GUtil::openFile(const QString &filePath)
{
QString appl;
QStringList argList;
#if defined(Q_OS_MACX)
appl = "open";
#elif defined(Q_OS_WIN)
appl = "cmd";
argList << "/C";
#else
return(false);
#endif
argList << filePath;
// create external application process
QProcess *proc = new QProcess(0);
// launch process
proc->start(appl, argList);
if (! proc->waitForStarted())
return(false);
else
return(true);
}

25
gui/GUtil.h

@ -0,0 +1,25 @@
//! GUtil class definitions.
/*!
* \file GUtil.h
*
* This file contains the GUtil class definition.
*/
#ifndef GUTIL_H
#define GUTIL_H
#include <QString>
//! Utility class.
/*!
* \class GUtil
*
* Defines a utility class.
*/
class GUtil
{
public:
static bool openFile(const QString &filePath);
};
#endif // GUTIL_H

25
gui/Qt_main.cpp

@ -0,0 +1,25 @@
//! The main GUCC function.
/*!
* \file Qt_main.cpp
*
* This file contains the main GUCC function.
*/
#include <QApplication>
#include "GMainWindow.h"
/*!
* Main function.
*
* \param argc number of arguments
* \param argv argument list
*
* \return function status
*/
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GMainWindow w;
w.show();
return a.exec();
}

60
gui/UCCWorker.cpp

@ -0,0 +1,60 @@
//! Qt Object interface to rest of UCC work to allow Qt Thread use
/*!
* \file UCCWorker.cpp
*
* This file encapsulates Qt implementation details and dependencies
* so that the rest of UCC is relatively unchanged.
*
* ADDED to UCC 2015_12 release by Randy Maxwell
* Changes started on 2015_12_03
* Changes ended on 2015_12_05
* Addition of Multithreading performance enhancement feature
* Example: UCC -threads 4 (to have 4 worker threads)
*/
#include "../src/UCCThread.h"
#ifdef ENABLE_THREADS
#include <QThread>
#include "UCCWorker.h"
// See UCCThread.cpp
extern void prv_WorkThread_Function( const unsigned int thr_array_idx );
void WorkerThread::run()
{
// Implement run to only call UCC
// to prevent any Event loops from running
prv_WorkThread_Function( thread_array_idx );
}
// Constructor to call to base class constructor
UCCWorker::UCCWorker()
{}
// Destructor to call to base class destructor
UCCWorker::~UCCWorker()
{}
// Provide a Qt Object wrapper
WorkerThread * UCCWorker::startWorkInAThread( const unsigned int thread_idx )
{
// Call into the thread procedure.
// This will run as long as needed.
WorkerThread *pWorkerThread = new WorkerThread;
pWorkerThread->thread_array_idx = thread_idx;
connect( pWorkerThread, SIGNAL( finished() ),
pWorkerThread, SLOT( deleteLater() ) );
// Start Qt Thread which will Call UCC worker thread proc
pWorkerThread->start();
return pWorkerThread;
}
#endif

50
gui/UCCWorker.h

@ -0,0 +1,50 @@
//! Qt Object interface to rest of UCC work to allow Qt Thread use
/*!
* \file UCCWorker.h
*
* This file encapsulates Qt Thread implementation details and dependencies
* so that the rest of UCC is relatively unchanged.
*
* ADDED to UCC 2015_12 release by Randy Maxwell
* Changes started on 2015_12_03
* Changes ended on 2015_12_03
* Addition of Multithreading performance enhancement feature
* Example: UCC -threads 4 (to have 4 worker threads)
*/
#ifndef UCCWORKER_H
#define UCCWORKER_H
#include "../src/UCCThread.h"
#ifdef ENABLE_THREADS
#include <QObject>
#include <QThread>
// Declare a class derived from the QThread
class WorkerThread : public QThread {
// Declare here
void run();
public:
unsigned int thread_array_idx;
};
// QT Object
class UCCWorker : public QObject
{
public:
UCCWorker();
~UCCWorker();
// Interface to do UCC processing
WorkerThread * startWorkInAThread( const unsigned int thread_idx );
};
#endif // ENABLE_THREADS
#endif // UCCWORKER_H

189
gui/gucc.pro

@ -0,0 +1,189 @@
# Modification: 2016.01; USC
# Updated included modules to support Qt 5.7
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4) {
QT += widgets
qtHaveModule(webengine) {
QT += webenginewidgets
} else {
qtHaveModule(webkit) {
DEFINES += NEED_WEBKIT_LEGACY
QT += webkitwidgets
} else {
DEFINES += NO_WEB_SUPPORT
warning(Compiling with no web support. Visual differencing integration will be disabled!)
}
}
} else {
DEFINES += NEED_WEBKIT_LEGACY
QT += webkit
}
CONFIG += qt warn_on debug_and_release no_batch
# Modification: 2016.01; USC
# Fixed mingw 4.9.1 compilation errors
CONFIG += c++11
TEMPLATE = app
LANGUAGE = C++
DEFINES += QTGUI
HEADERS += \
GAsciiDialog.h \
GExtensionDialog.h \
GMainWindow.h \
GSideBySideDialog.h \
GTableDialog.h \
GUtil.h\
../src/CAdaCounter.h \
../src/CBashCounter.h \
../src/CBatchCounter.h \
../src/cc_main.h \
../src/CCCounter.h \
../src/CCFScriptCounter.h \
../src/CCJavaCsScalaCounter.h \
../src/CCodeCounter.h \
../src/CColdFusionCounter.h \
../src/CCsharpCounter.h \
../src/CCshCounter.h \
../src/CCssCounter.h \
../src/CDataCounter.h \
../src/CFortranCounter.h \
../src/CHtmlCounter.h \
../src/CJavaCounter.h \
../src/CJavascriptCounter.h \
../src/CMakefileCounter.h \
../src/CMatlabCounter.h \
../src/CMidasCounter.h \
../src/CmpMngr.h \
../src/CNeXtMidasCounter.h \
../src/CObjCCounter.h \
../src/CPascalCounter.h \
../src/CPerlCounter.h \
../src/CPhpCounter.h \
../src/CPythonCounter.h \
../src/CRubyCounter.h \
../src/CSqlCounter.h \
../src/CTagCounter.h \
../src/CUtil.h \
../src/CVbCounter.h \
../src/CVbscriptCounter.h \
../src/CVerilogCounter.h \
../src/CVHDLCounter.h \
../src/CWebCounter.h \
../src/CXMidasCounter.h \
../src/CXmlCounter.h \
../src/DiffTool.h \
../src/MainObject.h \
../src/UserIF.h \
../src/CmpMngrHtml.h \
../src/CAssemblyCounter.h \
../src/CIdlCounter.h \
../src/UCCThread.h \
../src/UCCGlobals.h \
../src/UCCFilesOut.h \
../src/UCCExceptDump.h \
../src/sema.h \
../src/LangUtils.h \
../src/CScalaCounter.h \
../src/CCobolCounter.h \
../src/UCCAfterLibraryIncludes.h \
../src/UCCBeforeLibraryIncludes.h \
# Modification: 2017.02
../src/FunctionParser.h \
UCCWorker.h
SOURCES += \
GAsciiDialog.cpp \
GExtensionDialog.cpp \
GMainWindow.cpp \
GSideBySideDialog.cpp \
GTableDialog.cpp \
GUtil.cpp\
../src/CAdaCounter.cpp \
../src/CBashCounter.cpp \
../src/CBatchCounter.cpp \
../src/cc_main.cpp \
../src/CCCounter.cpp \
../src/CCFScriptCounter.cpp \
../src/CCJavaCsScalaCounter.cpp \
../src/CCodeCounter.cpp \
../src/CColdFusionCounter.cpp \
../src/CCsharpCounter.cpp \
../src/CCshCounter.cpp \
../src/CCssCounter.cpp \
../src/CDataCounter.cpp \
../src/CFortranCounter.cpp \
../src/CHtmlCounter.cpp \
../src/CJavaCounter.cpp \
../src/CJavascriptCounter.cpp \
../src/CMakefileCounter.cpp \
../src/CMatlabCounter.cpp \
../src/CMidasCounter.cpp \
../src/CmpMngr.cpp \
../src/CNeXtMidasCounter.cpp \
../src/CObjCCounter.cpp \
../src/CPascalCounter.cpp \
../src/CPerlCounter.cpp \
../src/CPhpCounter.cpp \
../src/CPythonCounter.cpp \
../src/CRubyCounter.cpp \
../src/CSqlCounter.cpp \
../src/CTagCounter.cpp \
../src/CUtil.cpp \
../src/CVbCounter.cpp \
../src/CVbscriptCounter.cpp \
../src/CVerilogCounter.cpp \
../src/CVHDLCounter.cpp \
../src/CWebCounter.cpp \
../src/CXMidasCounter.cpp \
../src/CXmlCounter.cpp \
../src/DiffTool.cpp \
../src/MainObject.cpp \
../src/UserIF.cpp \
../src/CmpMngrHtml.cpp \
../src/CAssemblyCounter.cpp \
../src/CIdlCounter.cpp \
../src/UCCThread.cpp \
../src/UCCGlobals.cpp \
../src/UCCFilesOut.cpp \
../src/UCCExceptDump.cpp \
../src/LangUtils.cpp \
../src/CScalaCounter.cpp \
../src/CCobolCounter.cpp \
../src/main.cpp \
# Modification: 2017.02
../src/FunctionParser.cpp \
Qt_main.cpp \
UCCWorker.cpp
FORMS += \
GAsciiDialog.ui \
GExtensionDialog.ui \
GMainWindow.ui \
GTableDialog.ui
RESOURCES += \
gucc.qrc
win32 {
TARGET = GUCC
UI_DIR = GeneratedFiles
RCC_DIR = GeneratedFiles
RC_FILE = GUCC.rc
#Modification: 2016.01; USC
#Fixed mingw 4.9.1 compilation errors
DEFINES += WIN32
}
unix {
UI_DIR = .ui
MOC_DIR = .moc
OBJECTS_DIR = .obj
DEFINES += UNIX
}
macx {
TARGET = GUCC
RC_FILE = images/gucc.icns
DEFINES += UNIX
}

15
gui/gucc.qrc

@ -0,0 +1,15 @@
<RCC>
<qresource prefix="/">
<file>images/add_folder.png</file>
<file>images/arrow.png</file>
<file>images/close.png</file>
<file>images/edit.png</file>
<file>images/gucc.png</file>
<file>images/help.png</file>
<file>images/minus_sign.png</file>
<file>images/open.png</file>
<file>images/plus_sign.png</file>
<file>images/start.png</file>
<file>images/stop.png</file>
</qresource>
</RCC>

BIN
gui/images/add_folder.png

After

Width: 256  |  Height: 256  |  Size: 9.0 KiB

BIN
gui/images/arrow.png

After

Width: 512  |  Height: 512  |  Size: 79 KiB

BIN
gui/images/close.png

After

Width: 32  |  Height: 32  |  Size: 1.1 KiB

BIN
gui/images/edit.png

After

Width: 32  |  Height: 32  |  Size: 2.0 KiB

BIN
gui/images/gucc.icns

BIN
gui/images/gucc.png

After

Width: 256  |  Height: 256  |  Size: 12 KiB

BIN
gui/images/help.png

After

Width: 32  |  Height: 32  |  Size: 2.0 KiB

BIN
gui/images/minus_sign.png

After

Width: 128  |  Height: 128  |  Size: 9.6 KiB

BIN
gui/images/open.png

After

Width: 32  |  Height: 32  |  Size: 1.7 KiB

BIN
gui/images/plus_sign.png

After

Width: 128  |  Height: 128  |  Size: 13 KiB

BIN
gui/images/start.png

After

Width: 32  |  Height: 32  |  Size: 979 B

BIN
gui/images/stop.png

After

Width: 32  |  Height: 32  |  Size: 1.2 KiB

208
license.txt

@ -0,0 +1,208 @@
UCC LICENSE
COPYRIGHT (C) 2006 - 2018
Center for Systems and Software Engineering
University of Southern California
Salvatori 330, 941 West 37th Place
Los Angeles, California 90089-0781, USA
This CodeCount program is free software with limitations; you can redistribute it and/or
modify it under the terms of the USC-CSSE Limited Public License as published by the
University of Southern California Center for Systems and Software Engineering; either version 1 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-------------------------------------------------------------------------------------------
USC-CSSE LIMITED PUBLIC LICENSE TERMS AND CONDITIONS
-------------------------------------------------------------------------------------------
The precise terms and conditions for copying, distribution and modification are as follows.
0. This License applies to any program or other work which contains a notice placed by the
copyright holder saying it may be distributed under the terms of this Limited Public
License. The "Program", below, refers to any such program or work, and a "work based on the
Program" means either the Program or any derivative work under copyright law: that is to
say, a work containing the Program or a portion of it, either verbatim or with
modifications and/or translated into another language. (Hereinafter, translation is
included without limitation in the term "modification".) Each licensee is addressed as
"you".
Activities other than copying, distribution and modification are not covered by this
License; they are outside its scope. The act of running the Program is not restricted nor
is the output from the Program is covered.
1. You may copy and distribute verbatim copies of the Program's source code as you receive
it, in any medium, provided that you conspicuously and appropriately publish on each copy
an appropriate copyright notice and disclaimer of warranty; keep intact all the notices
that refer to this License and to the absence of any warranty; and give any other
recipients of the Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you may at your
option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it, thus forming a
work based on the Program, and copy and distribute such modifications or work under the
terms of Section 1 above, provided that you also meet all of these conditions:
2.a) You must cause the modified files to carry prominent notices stating that you changed
the files and the date of any change.
2.b) You must cause any work that you distribute or publish, that in whole or in part
contains or is derived from the Program or any part thereof, to be licensed as a whole at
no charge to all third parties under the terms of this License.
2.c) If the modified program normally reads commands interactively when run, you must cause
it, when started running for such interactive use in the most ordinary way, to print or
display an announcement including an appropriate copyright notice and a notice that there
is no warranty (or else, saying that you provide a warranty) and that users may
redistribute the program under these conditions, and telling the user how to view a copy of
this License. (Exception: if the Program itself is interactive but does not normally print
such an announcement, your work based on the Program is not required to print an
announcement.)
2.d) You must provide a copy of the modified machine-readable source code files to the
University of Southern California Center for Systems and Software Engineering Salvatori 330,
941 West 37th Place, Los Angeles, California 90089-0781, USA, on an appropriate medium or
via our contact information at http://csse.usc.edu.
These requirements apply to the modified work as a whole. If identifiable sections of that
work are not derived from the Program, and can be reasonably considered independent and
separate works in themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you distribute the same
sections as part of a whole which is a work based on the Program, the distribution of the
whole must be on the terms of this License, whose permissions for other licensees extend to
the entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to work
written entirely by you; rather, the intent is to exercise the right to control the
distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the Program (or
with a work based on the Program) on a volume of a storage or distribution medium does not
bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2) in
object code or executable form under the terms of Sections 1 and 2 above provided that you
also do one of the following:
3.a) Accompany it with the complete corresponding machine-readable source code, which must
be distributed under the terms of Sections 1 and 2 above on a medium customarily used for
software interchange; or,
3.b) Accompany it with a written offer, valid for at least three years, to give any third
party, for a charge no more than your cost of physically performing source distribution, a
complete machine-readable copy of the corresponding source code, to be distributed under
the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
or,
3.c) Accompany it with the information you received as to the offer to distribute
corresponding source code. (This alternative is allowed only for noncommercial distribution
and only if you received the program in object code or executable form with such an offer,
in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifications to
it. For an executable work, complete source code means all the source code for all modules
it contains, plus any associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a special exception,
the source code distributed need not include anything that is normally distributed (in
either source or binary form) with the major components (compiler, kernel, and so on) of
the operating system on which the executable runs, unless that component itself accompanies
the executable.
If distribution of executable or object code is made by offering access to copy from a
designated place, then offering equivalent access to copy the source code from the same
place counts as distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly
provided under this License. Any attempt otherwise to copy, modify, sublicense or
distribute the Program is void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights, from you under this License
will not have their licenses terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it. However,
nothing else grants you permission to modify or distribute the Program or its derivative
works. These actions are prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the Program), you indicate your
acceptance of this License to do so, and all its terms and conditions for copying,
distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the Program), the recipient
automatically receives a license from the original licensor to copy, distribute or modify
the Program subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein. You are not
responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any
other reason (not limited to patent issues), conditions are imposed on you (whether by court
order, agreement or otherwise) that contradict the conditions of this License, they
do not excuse you from the conditions of this License. If you cannot distribute so as to
satisfy simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all. For example,
if a patent license would not permit royalty-free redistribution of the Program by all
those who receive copies directly or indirectly through you, then the only way you could
satisfy both it and this License would be to refrain entirely from distribution of the
Program.
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply and the section as a whole is
intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has the sole
purpose of protecting the integrity of this free software with limitations distribution
system, which is implemented by limited public license practices. Many people have made
generous contributions to the wide range of software distributed through that system in
reliance on consistent application of that system; it is up to the author/donor to decide
if he or she is willing to distribute software through any other system and a licensee
cannot impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence of
the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either
by patents or by copyrighted interfaces, the original copyright holder who places the
Program under this License may add an explicit geographical distribution limitation
excluding those countries, so that distribution is permitted only in or among countries not
thus excluded. In such case, this License incorporates the limitation as if written in the
body of this License.
9. The University of Southern California Center for Systems and Software Engineering may publish
revised and/or new versions of this Limited Public License from time to time. Such new
versions will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a version
number of this License which applies to it and "any later version", you have the option of
following the terms and conditions either of that version or of any later version published
by the University of Southern California Center for Systems and Software Engineering. If the Program
does not specify a version number of this License, you may choose any version ever
published by the University of Southern California Center for Systems and Software Engineering.
10. If you wish to incorporate parts of the Program into other free programs whose
distribution conditions are different, write to the author to ask for permission. For
software which is copyrighted by the University of Southern California Center for Software
Engineering, write to the University of Southern California Center for Systems and Software Engineering;
we sometimes make exceptions for this. Our decision will be guided by the goal of preserving
the free status of all derivatives of our free software with limitations.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO
THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE
COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE,
BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO
LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR
OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

23
src/BOOST_LICENSE_1_0.txt

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

783
src/CAdaCounter.cpp

@ -0,0 +1,783 @@
//! Code counter class methods for the Ada language.
/*!
* \file CAdaCounter.cpp
*
* This file contains the code counter class methods for the Ada language.
*/
#include "CAdaCounter.h"
/*!
* Constructs a CAdaCounter object.
*/
CAdaCounter::CAdaCounter()
{
classtype = ADA;
language_name = "Ada";
casesensitive = false;
//Modification: 11.2016 Ext-4 starts
file_extension = CUtil::getExtensionsToLanguage("Ada", file_extension);
/*
file_extension.push_back(".ada");
file_extension.push_back(".a");
file_extension.push_back(".adb");
file_extension.push_back(".ads");*/
//Modification: 11.2016 Ext-4
LineCommentStart.push_back("--");
QuoteStart = "\"";
QuoteEnd = "\"";
QuoteEscapeRear = '\"';
directive.push_back("controlled");
directive.push_back("elaborate");
directive.push_back("inline");
directive.push_back("interface");
directive.push_back("list");
directive.push_back("memory_size");
directive.push_back("optimize");
directive.push_back("pack");
directive.push_back("page");
directive.push_back("pragma");
directive.push_back("priority");
directive.push_back("shared");
directive.push_back("storage_unit");
directive.push_back("suppress");
directive.push_back("system_name");
data_name_list.push_back("access");
data_name_list.push_back("array");
data_name_list.push_back("body");
data_name_list.push_back("constant");
data_name_list.push_back("declare");
data_name_list.push_back("function");
data_name_list.push_back("generic");
data_name_list.push_back("limited");
data_name_list.push_back("new");
data_name_list.push_back("package");
data_name_list.push_back("private");
data_name_list.push_back("procedure");
data_name_list.push_back("record");
data_name_list.push_back("renames");
data_name_list.push_back("separate");
data_name_list.push_back("subtype");
data_name_list.push_back("task");
data_name_list.push_back("type");
data_name_list.push_back("use");
data_name_list.push_back("with");
exec_name_list.push_back("abort");
exec_name_list.push_back("accept");
exec_name_list.push_back("begin");
exec_name_list.push_back("case");
exec_name_list.push_back("delay");
exec_name_list.push_back("else");
exec_name_list.push_back("elsif");
exec_name_list.push_back("end");
exec_name_list.push_back("entry");
exec_name_list.push_back("exception");
exec_name_list.push_back("exit");
exec_name_list.push_back("goto");
exec_name_list.push_back("if");
exec_name_list.push_back("loop");
exec_name_list.push_back("others");
exec_name_list.push_back("raise");
exec_name_list.push_back("return");
exec_name_list.push_back("select");
exec_name_list.push_back("terminate");
exec_name_list.push_back("when");
math_func_list.push_back("exp");
math_func_list.push_back("random");
math_func_list.push_back("sqrt");
trig_func_list.push_back("arccos");
trig_func_list.push_back("arccosh");
trig_func_list.push_back("arccot");
trig_func_list.push_back("arccoth");
trig_func_list.push_back("arcsin");
trig_func_list.push_back("arcsinh");
trig_func_list.push_back("arctan");
trig_func_list.push_back("arctanh");
trig_func_list.push_back("cos");
trig_func_list.push_back("cosh");
trig_func_list.push_back("cot");
trig_func_list.push_back("coth");
trig_func_list.push_back("sin");
trig_func_list.push_back("sinh");
trig_func_list.push_back("tan");
trig_func_list.push_back("tanh");
log_func_list.push_back("log");
cmplx_calc_list.push_back("+");
cmplx_calc_list.push_back("-");
cmplx_calc_list.push_back("*");
cmplx_calc_list.push_back("/");
cmplx_calc_list.push_back("mod");
cmplx_calc_list.push_back("rem");
cmplx_cond_list.push_back("case");
cmplx_cond_list.push_back("else");
cmplx_cond_list.push_back("elsif");
cmplx_cond_list.push_back("if");
cmplx_cond_list.push_back("loop");
cmplx_cond_list.push_back("when");
cmplx_logic_list.push_back("=");
cmplx_logic_list.push_back("<");
cmplx_logic_list.push_back(">");
cmplx_logic_list.push_back("/=");
cmplx_logic_list.push_back(">=");
cmplx_logic_list.push_back("<=");
cmplx_logic_list.push_back("&");
cmplx_logic_list.push_back("and");
cmplx_logic_list.push_back("or");
cmplx_logic_list.push_back("xor");
cmplx_logic_list.push_back("in");
cmplx_logic_list.push_back("not in");
cmplx_preproc_list.push_back("controlled");
cmplx_preproc_list.push_back("elaborate");
cmplx_preproc_list.push_back("inline");
cmplx_preproc_list.push_back("interface");
cmplx_preproc_list.push_back("list");
cmplx_preproc_list.push_back("memory_size");
cmplx_preproc_list.push_back("optimize");
cmplx_preproc_list.push_back("pack");
cmplx_preproc_list.push_back("page");
cmplx_preproc_list.push_back("pragma");
cmplx_preproc_list.push_back("priority");
cmplx_preproc_list.push_back("shared");
cmplx_preproc_list.push_back("storage_unit");
cmplx_preproc_list.push_back("suppress");
cmplx_preproc_list.push_back("system_name");
cmplx_assign_list.push_back(":=");
//cmplx_cyclomatic_list.push_back("if");
cmplx_cyclomatic_list.push_back("if");
cmplx_cyclomatic_list.push_back("elsif");
//cmplx_cyclomatic_list.push_back("IIf");
cmplx_cyclomatic_list.push_back("for");
cmplx_cyclomatic_list.push_back("while");
//cmplx_cyclomatic_list.push_back("Until");
//cmplx_cyclomatic_list.push_back("Catch");
cmplx_cyclomatic_list.push_back("when");
//cmplx_cyclomatic_list.push_back("case");
ignore_cmplx_cyclomatic_list.push_back("end if");
//cmplx_cyclomatic_logic_list.push_back("&");
cmplx_cyclomatic_logic_list.push_back("and");
cmplx_cyclomatic_logic_list.push_back("or");
//cmplx_cyclomatic_logic_list.push_back("xor");
cmplx_cyclomatic_case_list.push_back("when");
cmplx_cyclomatic_switch_list.push_back("end case");
cmplx_cyclomatic_default_list.push_back("others");
}
/*!
* Replaces quoted strings inside a string starting at idx_start with '$'.
* Handles special cases for Ada literal strings.
*
* \param strline string to be processed
* \param idx_start index of line character to start search
* \param contd specifies the quote string is continued from the previous line
* \param CurrentQuoteEnd end quote character of the current status
*
* \return method status
*/
int CAdaCounter::ReplaceQuote(string &strline, size_t &idx_start, bool &contd, char &CurrentQuoteEnd)
{
size_t idx = 0;
bool done = false;
while( ! done )
{
idx = strline.find("'\"'", idx); // replace all '"' by '$'
if (idx != string::npos)
strline.replace(idx, 3, 3, '$');
else
break;
}
return CCodeCounter::ReplaceQuote(strline, idx_start, contd, CurrentQuoteEnd);
}
/*!
* Counts directive lines of code.
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CAdaCounter::CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapBak)
{
bool contd = false, trunc_flag = false;
size_t idx, strSize;
unsigned int cnt = 0;
string strDirLine = "";
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$:";
filemap::iterator itfmBak = fmapBak->begin();
for (filemap::iterator iter = fmap->begin(); iter != fmap->end(); iter++, itfmBak++)
{
if (CUtil::CheckBlank(iter->line))
continue;
size_t lineNumber = iter->lineNumber;
if (print_cmplx)
{
cnt = 0;
CUtil::CountTally(" " + iter->line, directive, cnt, 1, exclude, "", "", &result->directive_count, false);
}
if (!contd)
{
// if not a continuation of a previous directive
for (vector<string>::iterator viter = directive.begin(); viter != directive.end(); viter++)
{
// merged bug fix for considering only stand-alone keywords
// e.g. package should not be considered a directive (only 'pack' is)
if (((idx = CUtil::FindKeyword(iter->line, *viter, 0, TO_END_OF_STRING, false)) != string::npos) && idx == 0)
{
contd = true;
break;
}
}
if (contd)
{
strSize = CUtil::TruncateLine(itfmBak->line.length(), 0, this->lsloc_truncate, trunc_flag);
if (strSize > 0)
strDirLine = itfmBak->line.substr(0, strSize);
result->directive_lines[PHY]++;
}
}
else
{
// continuation of a previous directive
strSize = CUtil::TruncateLine(itfmBak->line.length(), strDirLine.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
strDirLine += "\n" + itfmBak->line.substr(0, strSize);
result->directive_lines[PHY]++;
}
if (contd)
{
// drop continuation symbol
if (strDirLine[strDirLine.length()-1] == '\\')
strDirLine = strDirLine.substr(0, strDirLine.length()-1);
// if a directive or continuation of a directive (no continuation symbol found)
if (iter->line[iter->line.length()-1] != ',' && iter->line[iter->line.length()-1] != '\\')
{
contd = false;
if (result->addSLOC(strDirLine, lineNumber, trunc_flag))
result->directive_lines[LOG]++;
}
iter->line = "";
}
}
return 1;
}
/*!
* Processes physical and logical lines according to language specific rules.
* NOTE: all the blank lines +
* whole line comments +
* lines with compiler directives
* should have been blanked from filemap by previous processing
* before reaching this function
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CAdaCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak)
{
bool found_accept = false;
string strLSLOC = "";
string strLSLOCBak = "";
unsigned int cnt = 0;
unsigned int loopLevel = 0;
filemap::iterator fit, fitbak;
string line, lineBak, tmp;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$:";
unsigned int l_paren_cnt = 0;
bool l_foundblock, found_forifwhile, found_end, found_type, found_is;
l_foundblock = found_forifwhile = found_end = found_is = false;
for (fit = fmap->begin(), fitbak = fmapBak->begin(); fit != fmap->end(); fit++, fitbak++)
{
// insert blank at the beginning (for searching keywords)
line = ' ' + fit->line;
lineBak = ' ' + fitbak->line;
if (!CUtil::CheckBlank(line))
{
// blank line means blank_line/comment_line/directive
// call SLOC function to detect logical SLOC and add to result
LSLOC(result, line, fit->lineNumber, lineBak, strLSLOC, strLSLOCBak, l_paren_cnt, l_foundblock,
found_forifwhile, found_end, found_type, found_is, found_accept, loopLevel);
cnt = 0;
CUtil::CountTally(line, data_name_list, cnt, 1, exclude, "", "", NULL, false);
// need to check also if the data line continues
if (cnt > 0)
result->data_lines[PHY]++;
else
result->exec_lines[PHY]++;
if (print_cmplx)
{
cnt = 0;
CUtil::CountTally(line, exec_name_list, cnt, 1, exclude, "", "", &result->exec_name_count, false);
}
}
}
return 1;
}
/*!
* Processes a logical line of code.
* This method is called after a logical SLOC is determined.
* The method adds LSLOC to the result, increases counts, and resets variables.
*
* \param result counter results
* \param strLSLOC processed logical string
* \param strLSLOCBak original logical string
* \param found_block found block flag
* \param found_forifwhile found for, if, or while flag
* \param found_end found end flag
* \param found_type found type flag
* \param found_is found is flag
* \param found_accept found accept flag
* \param trunc_flag truncate lines?
*/
void CAdaCounter::FoundSLOC(results* result, size_t lineNumber, string &strLSLOC, string &strLSLOCBak, bool &found_block, bool &found_forifwhile,
bool &found_end, bool &found_type, bool &found_is, bool &found_accept, bool &trunc_flag)
{
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$:";
// add to the list for comparison purpose
if (result->addSLOC(CUtil::TrimString(strLSLOCBak), lineNumber, trunc_flag))
{
// determine logical type, data declaration or executable
unsigned int cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", &result->data_name_count, false);
if (cnt > 0)
result->data_lines[LOG]++;
else
result->exec_lines[LOG]++;
}
// reset all variables whenever a new statement/logical SLOC is found
strLSLOC = "";
strLSLOCBak = "";
found_block = false;
found_forifwhile = false;
found_end = false;
found_type = false;
found_is = false;
found_accept = false;
}
/*!
* Extracts and stores logical lines of code.
* Determines and extract logical SLOC to place in the result variable
* using addSLOC function. Each time the addSLOC function is called,
* a new logical SLOC is added. This function assumes that the directive
* is handled before it is called.
*
* \param result counter results
* \param line processed physical line of code
* \param lineBak original physical line of code
* \param strLSLOC processed logical string
* \param strLSLOCBak original logical string
* \param paren_cnt count of parenthesis
* \param found_block found block flag
* \param found_forifwhile found for, if, or while flag
* \param found_end found end flag
* \param found_type found type flag
* \param found_is found is flag
* \param found_accept found accept flag
* \param loopLevel nested loop level
*/
void CAdaCounter::LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
unsigned int &paren_cnt, bool &found_block, bool &found_forifwhile, bool &found_end,
bool &found_type, bool &found_is, bool &found_accept, unsigned int &loopLevel)
{
size_t start = 0; //starting index of the working string
size_t i = 0, tempi, strSize;
string templine = CUtil::TrimString(line);
string tmp;
bool trunc_flag = false;
string keywordchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
// there may be more than 1 logical SLOC in a line
for (i = 0; i < line.length(); i++)
{
switch (line[i])
{
case ';':
/*if (paren_cnt > 0)
break;*/ //this is not necessary
if (!found_end)
{
// check for empty statement (=1 LSLOC)
if (CUtil::TrimString(line.substr(start, i + 1 - start)) == ";" && strLSLOC.length() < 1)
{
strLSLOC = ";";
strLSLOCBak = ";";
}
else
{
strSize = CUtil::TruncateLine(i - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
}
else
{
found_end = false; // end xxx
found_block = false;
found_is = false;
found_forifwhile = false;
found_type = false;
found_accept = false;
strLSLOC = "";
strLSLOCBak = "";
}
start = i + 1;
break;
case '(':
if (found_type)
found_type = false;
paren_cnt++;
break;
case ')':
if (paren_cnt > 0)
paren_cnt--;
break;
}
// continue the following processing only if line[i] is not in a middle of a word
if (keywordchars.find(line[i]) != string::npos && i < line.length() - 1)
continue;
// if it ends in xxx, then it has already been counted, so ignore it
tmp = "xxx " + CUtil::TrimString(line.substr(start, i + 1 - start));
tempi = CUtil::FindKeyword(tmp, "end", 0, TO_END_OF_STRING, false);
if (tempi != string::npos)
{
found_end = true;
// record end loop for nested loop processing
if (print_cmplx)
{
tmp = CUtil::TrimString(line.substr(start, i + 5 - start));
if (CUtil::FindKeyword(tmp, "end loop", 0, TO_END_OF_STRING, false) != string::npos)
if (loopLevel > 0)
loopLevel--;
}
start = i + 1;
}
if (!found_end)
{
if (!found_forifwhile)
{
if (CUtil::FindKeyword(tmp, "for", 0 , TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "while", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "if", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "elsif", 0, TO_END_OF_STRING, false) != string::npos)
{
found_forifwhile = true;
}
// 'exception' is removed because it is not counted
if (CUtil::FindKeyword(tmp, "loop", 0, TO_END_OF_STRING, false) != string::npos)
{
// found a SLOC
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
start = i + 1;
// record nested loop level
if (print_cmplx)
{
loopLevel++;
if ((unsigned int)result->cmplx_nestloop_count.size() < loopLevel)
result->cmplx_nestloop_count.push_back(1);
else
result->cmplx_nestloop_count[loopLevel-1]++;
}
continue;
}
}
else if (CUtil::FindKeyword(tmp, "loop", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "then", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "record", 0, TO_END_OF_STRING, false) != string::npos) // for..use..record
{
// found a SLOC
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
start = i + 1;
// record nested loop level
if (print_cmplx)
{
if (CUtil::FindKeyword(tmp, "loop", 0, TO_END_OF_STRING, false) != string::npos)
{
loopLevel++;
if ((unsigned int)result->cmplx_nestloop_count.size() < loopLevel)
result->cmplx_nestloop_count.push_back(1);
else
result->cmplx_nestloop_count[loopLevel-1]++;
}
}
continue;
}
// similarly, check for procedure, task, function - it ends with 'is' keyword
// procedure ... is...
// package ... is ...
if (!found_block)
{
if (CUtil::FindKeyword(tmp, "procedure", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "function", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "package", 0, TO_END_OF_STRING, false) !=string::npos ||
CUtil::FindKeyword(tmp, "task", 0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "case",0, TO_END_OF_STRING, false) != string::npos ||
CUtil::FindKeyword(tmp, "protected", 0, TO_END_OF_STRING, false) != string::npos)
{
found_block = true;
}
}
else // procedure...is...
{
// the 'if' statement below attempts to 'alleviate' the issue with
// procedure Swap is new Exchange(Elem => Integer);
// procedure Test1 is begin end Test1;
// only add new SLOC if 'is' is at the end of line and follows 'procedure', etc.
// NOTE: this implementation may not be complete
tempi = CUtil::FindKeyword(templine, "is", 0, TO_END_OF_STRING, false);
if (tempi == templine.length() - 2)
{
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
start = i + 1;
found_is = true;
continue;
}
}
if (!found_type)
{
if (CUtil::FindKeyword(tmp, "type", 0, TO_END_OF_STRING, false) != string::npos)
found_type = true;
}
else
{
if (CUtil::FindKeyword(tmp, "record", 0, TO_END_OF_STRING, false) != string::npos)
{
// the 'if' statement below attempts to resolves the issue with
// type Expression is tagged null record;
// so, ignore this case.
// NOTE: this implementation may not be complete
if (templine.at(templine.length() - 1) != ';')
{
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
start = i + 1;
continue;
}
}
}
// process 'select...end select;', 'accept ... end accept;'
// 'record ... end record;' is handled via 'type'
// select ... end select; --> only one word statement 'select'
// accept id... do ... end [id]; --> SLOC starting from 'accept' to 'do'
// find 'do' only already found 'accept'
if (CUtil::FindKeyword(tmp, "select", 0, TO_END_OF_STRING, false) != string::npos)
{
// found 'select' statement, one SLOC
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
start = i + 1;
continue;
}
if (!found_accept)
{
if (CUtil::FindKeyword(tmp, "accept", 0, TO_END_OF_STRING, false) != string::npos)
found_accept = true;
}
else
{
if (CUtil::FindKeyword(tmp, "do", 0, TO_END_OF_STRING, false) != string::npos)
{
// found a SLOC
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
FoundSLOC(result, lineNumber, strLSLOC, strLSLOCBak, found_block, found_forifwhile,
found_end, found_type, found_is, found_accept, trunc_flag);
start = i + 1;
}
}
}
}
tmp = CUtil::TrimString(line.substr(start, i - start));
strSize = CUtil::TruncateLine(tmp.length(), strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += tmp.substr(0, strSize);
tmp = CUtil::TrimString(lineBak.substr(start, i - start));
strLSLOCBak += tmp.substr(0, strSize);
// drop continuation symbol
if (strLSLOC[strLSLOC.length()-1] == '\\')
{
strLSLOC = strLSLOC.substr(0, strLSLOC.length()-1);
strLSLOCBak = strLSLOCBak.substr(0, strLSLOCBak.length()-1);
}
}
if (tmp == "")
found_forifwhile = false;
}
/*!
* Parses lines for function/method names.
*
* \param line line to be processed
* \param lastline last line processed
* \param functionStack stack of functions
* \param functionName function name found
* \param functionCount function count found
*
* \return 1 if function name is found
*/
int CAdaCounter::ParseFunctionName(const string &line, string &/*lastline*/,
filemap &functionStack, string &functionName, unsigned int &functionCount)
{
string str;
size_t idx;
//unsigned int fcnt; waring fix
idx = CUtil::FindKeyword(line, "procedure");
if (idx != string::npos)
{
if (idx + 10 < line.length())
{
str = line.substr(idx + 10);
idx = str.find("is");
if (idx != string::npos)
{
str = CUtil::ClearRedundantSpaces(str.substr(0, idx));
}
lineElement element(++functionCount, str);
functionStack.push_back(element);
}
}
else
{
idx = CUtil::FindKeyword(line, "function");
if (idx != string::npos)
{
if (idx + 9 < line.length())
{
str = line.substr(idx + 9);
idx = str.find("(");
if (idx != string::npos)
{
str = CUtil::ClearRedundantSpaces(str.substr(0, idx));
}
lineElement element(++functionCount, str);
functionStack.push_back(element);
}
}
}
idx = CUtil::FindKeyword(line, "with");
if (idx == string::npos)
{
idx = CUtil::FindKeyword(line, "use");
if (idx == string::npos)
{
if (functionStack.empty())
{
// dealing with some code out of any subroutines, it a "main" code
return 2;
}
}
}
idx = CUtil::FindKeyword(line, "end");
if (idx != string::npos)
{
// Modification: 2018.01
if (!functionStack.empty())
{
idx = line.find(functionStack.back().line);
if (idx != string::npos)
{
functionName = functionStack.back().line;
functionCount = functionStack.back().lineNumber;
functionStack.pop_back();
return 1;
}
}
}
return 0;
}

48
src/CAdaCounter.h

@ -0,0 +1,48 @@
//! Code counter class definition for the Ada language.
/*!
* \file CAdaCounter.h
*
* This file contains the code counter class definition for the Ada language.
*/
#ifndef AdaCounter_h
#define AdaCounter_h
#include "CCodeCounter.h"
//! Ada code counter class.
/*!
* \class CAdaCounter
*
* Defines the Ada code counter class.
*/
class CAdaCounter : public CCodeCounter
{
public:
CAdaCounter();
protected:
virtual int CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapBak = NULL);
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak = NULL);
virtual int ReplaceQuote(string &strline, size_t &idx_start, bool &contd, char &CurrentQuoteEnd);
void LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
unsigned int &paren_cnt, bool &forflag, bool &found_forifwhile, bool &found_while, bool &found_type, bool &found_is, bool &found_accept, unsigned int &loopLevel);
void FoundSLOC(results* result, size_t lineNumber, string &strLSLOC, string &strLSLOCBak, bool &found_block, bool &found_forifwhile,
bool &found_end, bool &found_type, bool &found_is, bool &found_accept, bool &trunc_flag);
int ParseFunctionName(const string &line, string &lastline,
filemap &functionStack, string &functionName, unsigned int &functionCount);
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CAdaCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CAdaCounter(const CAdaCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CAdaCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CAdaCounter operator=(const CAdaCounter); // Declare without implementation
};
#endif

299
src/CAssemblyCounter.cpp

@ -0,0 +1,299 @@
//! Code counter class methods for assembly languages.
/*!
* \file CAssemblyCounter.cpp
*
* This file contains the code counter class methods for the assembly languages.
* To-do: Globalize changeMode using struct
*/
#include "CAssemblyCounter.h"
/*!
* Constructs a CAssemblyCounter object.
*/
CAssemblyCounter::CAssemblyCounter()
{
classtype = ASSEMBLY;
language_name = "Assembly";
//Modification: 11.2016 Ext-4 starts
file_extension = CUtil::getExtensionsToLanguage("Assembly", file_extension);
/*file_extension.push_back(".asm");
file_extension.push_back(".s");
file_extension.push_back(".asm.ppc");*/
//Modification: 11.2016 Ext-4 ends
statementSeparator = ";"; // assume it is ';' unless it conflicts with comment marker
BlockCommentStart.push_back("/*");
BlockCommentEnd.push_back("*/");
ContinueLine = "\\";
// .data & .bss section declaration storage mapping classes, which define data declaration
// see documentation: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/topic/com.ibm.aix.aixassem/doc/alangref/csect.htm#wyl350ken
data_declaration_code.push_back("RW");
data_declaration_code.push_back("TC0");
data_declaration_code.push_back("TC");
data_declaration_code.push_back("TD");
data_declaration_code.push_back("UA");
data_declaration_code.push_back("DS");
data_declaration_code.push_back("BS");
data_declaration_code.push_back("UC");
data_declaration_code.push_back("ER");
data_declaration_code.push_back("SD");
data_declaration_code.push_back("LD");
data_declaration_code.push_back("CM");
}
/*!
* Perform preprocessing of file lines before counting.
*
* \param fmap list of file lines
*
* \return method status
*/
int CAssemblyCounter::PreCountProcess(filemap* fmap)
{
FindLineCommentMarker(fmap);
return 0;
}
/*!
* Detect the character(s) that is used for marking a line as a comment line.
* If such a character is found, it is added to LineCommentStart vector.
* Since assembly code counter covers multiple assembly languages, there can be
* mulitple markers in the same program.
* GNU Assembler, for instance, supports # and ; for comment lines
*
* \param fmap list of file lines
*
*/
void CAssemblyCounter::FindLineCommentMarker(filemap* fmap)
{
StringVector markerChecklist; // contains line comment markers that need to be checked/tested
markerChecklist.push_back("#");
markerChecklist.push_back(";");
markerChecklist.push_back("|");
LineCommentStart.clear(); // remove all existing values just in case it was set unintentionally
/* Algorithm:
1. Read each line
a. For each comment marker, find position/index of the marker
i. If position is 0, a marker is found
1. Save/add the marker: LineCommentStart.push_back()
2. Remove the marker from the check list
ii. If position is > 0 && not last index && (position-1) is a space, a marker is found.
1. Save/add the marker: LineCommentStart.push_back()
2. Remove the marker from the check list
*/
StringVector::iterator nextMarker;
string line;
size_t position;
for (filemap::iterator fit = fmap->begin(); fit != fmap->end(); fit++)
{
line = fit->line;
nextMarker = markerChecklist.begin();
while (nextMarker != markerChecklist.end())
{
position = line.find(*nextMarker);
if (position == string::npos)
{
nextMarker++;
continue;
}
else if (position == 0)
{
LineCommentStart.push_back(*nextMarker);
nextMarker = markerChecklist.erase(nextMarker);
}
else if (position > 0 && position != (line.length() - 1) && line.at(position - 1) == ' ')
{
LineCommentStart.push_back(*nextMarker);
nextMarker = markerChecklist.erase(nextMarker);
}
else
nextMarker++;
}
}
}
/*!
* Processes physical and logical lines according to language specific rules.
* NOTE: all the blank lines +
* whole line comments
* should have been blanked from filemap by previous processing
* before reaching this function
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CAssemblyCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* /*fmapBak*/)
{
string logicalLine, nextPhysicalLine, physicalLine;
unsigned int i;
int changeSectionMode;
bool isDataSection = false;
bool isDataDeclarationLine = false; // specifies whether a given single line is the declaration of a data section (i.e. '.data')
bool hasLineContinuation = false;
int countPhysicalLine = 0;
for (filemap::iterator iter = fmap->begin(); iter != fmap->end(); iter++)
{
// A physical line does not contain trailing or leading spaces.
// nextPhysicalLine may contains multiple logical statements separated by a separator.
// nextPhysicalLine may end with a line continuation character.
// In this case, nextPhysicalLine will be constructed as multiple physical lines.
nextPhysicalLine = iter->line;
if (!hasLineContinuation)
physicalLine = "";
// do not process blank lines - blank line means blank_line/comment_line
if (!CUtil::CheckBlank(nextPhysicalLine))
{
countPhysicalLine++; // keep track of the number of physical lines (blank is not a physical line)
if (CUtil::EndsWith(nextPhysicalLine, "\\"))
{
physicalLine += nextPhysicalLine.substr(0, nextPhysicalLine.length() - 1) + " ";
hasLineContinuation = true;
continue; // go to next physical line
}
else
{
physicalLine += nextPhysicalLine;
hasLineContinuation = false;
}
isDataDeclarationLine = false;
// since a physical line may contain multiple logical lines, check for statement separator
StringVector tokens = CUtil::Split(physicalLine, statementSeparator);
for (i = 0; i < tokens.size(); i++)
{
logicalLine = CUtil::TrimString(tokens[i], 0); // one logical line
changeSectionMode = SwitchSectionMode(logicalLine);
if (changeSectionMode == 1)
isDataSection = false; // false means it is in executable section, not data section
else if (changeSectionMode == 2)
{
isDataSection = true; // true means it has entered a data section of the program
isDataDeclarationLine = true; // declaration of a data section (i.e. '.data') itself will not be counted as data line, but counted as executable
}
/*
Some Logical SLOC Counting Rules:
1) MyLabel: instr 1 LSLOC since instruction is present on the same line as the label
2) MyLabel: 0 LSLOC. Label without instruction is not an executable statement
3) .instruction param 1 LSLOC
4) .instruction 1 LSLOC. Some instructions do not require parameters
5) # 0 LSLOC since comment line. Comment lines have been taken care of in previous processing. No processing needed here
6) ; 0 LSLOC. Logical statement separator. Program will parse into multiple lines for processing
7) instr 1 LSLOC. If a line passes all of the above filter/exception, it is an executable line
Reference: http://www.ibm.com/developerworks/library/l-ppc/
*/
// The strategy is to figure out what should be excluded from counting (these are known as counting exceptions).
// Those lines that are not excluded will be assumed to be instructions; thus, they will be counted.
// 1. First exception to look for is mylabel:
// Rationale: label without instruction is not counted as a logical SLOC
if (CUtil::EndsWith(logicalLine, ":", true))
continue;
// 2. Do not count the following NASM statements: %endmacro, %endif, %endrep
if (CUtil::StartsWith(logicalLine, "%end", true))
continue;
// 3. Do not count the following MASM statements: endm, endp, ends, endw, end, .end, .endw
// and do not count the following GAS statements: .end, .endm, .endef, .endfunc, .endif, .endloop
if (CUtil::StartsWith(logicalLine, ".end", true) || CUtil::StartsWith(logicalLine, "end", true))
continue;
// anything that has passed the above exceptions is a logical SLOC that will be counted as 1 instruction
if (isDataSection && !isDataDeclarationLine)
result->data_lines[LOG]++;
else
result->exec_lines[LOG]++;
bool trunc_flag = false;
CUtil::TruncateLine(physicalLine.length(), logicalLine.length(), this->lsloc_truncate, trunc_flag);
result->addSLOC(logicalLine, trunc_flag); // add SLOC so that diff can be performed
}
if (isDataSection && !isDataDeclarationLine)
result->data_lines[PHY] += countPhysicalLine;
else
result->exec_lines[PHY] += countPhysicalLine;
countPhysicalLine = 0;
}
}
return 1;
}
/*!
* Determine whether or not to switch to text mode, data mode or no change from previous setting.
*
* \param statement statement text
*
* \return 0 for no change, 1 for text section, and 2 for data section.
*/
int CAssemblyCounter::SwitchSectionMode(const string &statement)
{
const int noChange = 0;
const int textSection = 1;
const int dataSection = 2;
string lStatement = CUtil::ToLower(statement);
// 1. Data section usually starts with .data (or its variances) or .bss, while code section starts with .text
if (lStatement.substr(0, 13) == "section .data" || lStatement.substr(0, 12) == "section .bss" || // NASM syntax for data section declaration
lStatement.substr(0, 5) == ".data" || lStatement.substr(0, 6) == ".const" || // MASM & GAS syntax for data section
lStatement.substr(0, 4) == ".bss" || // GAS syntax here & below
(lStatement.substr(0, 9) == ".section " && // find: .section name["flag"]. This is GAS syntax
(lStatement.find("\"d\"", 10) != string::npos || lStatement.find("\'d\'", 10) != string::npos || // find: "d" or 'd'
lStatement.find("\"b\"", 10) != string::npos || lStatement.find("\'b\'", 10) != string::npos)) || // or "b" or 'b'
lStatement.substr(0, 6) == ".rdata" || lStatement.substr(0, 6) == ".sdata" || lStatement.substr(0, 6) == ".kdata" || // MIPS syntax
lStatement.substr(0, 5) == ".sbss" || lStatement.substr(0, 4) == ".lit") //.lit8 and .lit4 are data sections for MIPS syntax
{
return dataSection;
}
else if (lStatement.substr(0, 13) == "section .text" || // NASM syntax for executable section declaration
lStatement.substr(0, 12) == "section .txt" || // NASM syntax only
lStatement.substr(0, 5) == ".code" || // MASM syntax only
lStatement.substr(0, 14) == ".section .text" || // GAS syntax
lStatement.substr(0, 5) == ".text" || // GAS, PowerPC, MIPS
lStatement.substr(0, 5) == ".init" || lStatement.substr(0, 5) == ".fini" || // MIPS syntax
lStatement.substr(0, 6) == ".ktext") // SPIM MIPS syntax
{
return textSection;
}
else if (lStatement.substr(0, 6) == ".csect") // only apply to PowerPC
{
// 2. A text section and a data section can also be defined by .csect instruction.
// Whether .csect is data or text depends on the given storage mapping classes.
// Data section can also be defined by .csect [name][storageMappingClass], where
// storageMappingClass is one of classes for .data or .bss.
// See .csect documentation: http://publib.boulder.ibm.com/infocenter/pseries/v5r3/topic/com.ibm.aix.aixassem/doc/alangref/csect.htm#wyl350ken
// since both [] and {} are supported, easier to convert {} to [] so that there is only one thing to deal with
lStatement = CUtil::ReplaceWith(CUtil::ReplaceWith(lStatement, "{", "["), "}", "]");
StringVector::iterator vit;
for (vit = data_declaration_code.begin(); vit != data_declaration_code.end(); vit++)
{
string strToFind = "[" + CUtil::ToLower(*vit) + "]";
if (lStatement.find(strToFind, 6) != string::npos)
return dataSection;
}
return textSection; // it was a .csect, but not a data .csect. Therefore, it is assumed to be a text .csect
}
return noChange; // if it is neither data nor text, mode change is NOT needed
}

45
src/CAssemblyCounter.h

@ -0,0 +1,45 @@
//! Code counter class definition for assembly languages
/*!
* \file CAssemblyCounter.h
*
* This file contains the code counter class definition for assembly languages.
*/
#ifndef CAssemblyCounter_h
#define CAssemblyCounter_h
#include "CCodeCounter.h"
//! Assembly code counter class.
/*!
* \class CAssemblyCounter
*
* Defines the assembly code counter class.
*/
class CAssemblyCounter : public CCodeCounter
{
public:
CAssemblyCounter();
protected:
virtual int PreCountProcess(filemap* /*fmap*/);
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapmBak = NULL);
int SwitchSectionMode(const string &statement); // data mode or text mode
void FindLineCommentMarker(filemap* fmap);
StringVector data_declaration_code; //!< storage mapping codes to define data declaration statements
string statementSeparator;
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CAssemblyCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CAssemblyCounter(const CAssemblyCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CAssemblyCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CAssemblyCounter operator=(const CAssemblyCounter); // Declare without implementation
};
#endif

947
src/CBashCounter.cpp

@ -0,0 +1,947 @@
//! Code counter class methods for the Bash shell script language.
/*!
* \file CBashCounter.cpp
*
* This file contains the code counter class methods for the Bash shell script language.
* This also includes the Korn shell language.
*/
#include "CBashCounter.h"
/*!
* Constructs a CBashCounter object.
*/
CBashCounter::CBashCounter()
{
classtype = BASH;
language_name = "Bash";
//Modification: 11.2016 Ext-4 starts
file_extension = CUtil::getExtensionsToLanguage("Bash", file_extension);
/*
file_extension.push_back(".sh");
file_extension.push_back(".ksh");
//Modification: 11.2016 Ext-4 ends*/
QuoteStart = "\"'";
QuoteEnd = "\"'";
QuoteEscapeFront = '\\';
ContinueLine = "\\";
LineCommentStart.push_back("#");
directive.push_back("#!");
exclude_keywords.push_back("done");
exclude_keywords.push_back("esac");
exclude_keywords.push_back("fi");
continue_keywords.push_back("do");
continue_keywords.push_back("else");
continue_keywords.push_back("then");
data_name_list.push_back("declare");
data_name_list.push_back("local");
data_name_list.push_back("type");
data_name_list.push_back("typeset");
exec_name_list.push_back("alias");
exec_name_list.push_back("awk");
exec_name_list.push_back("bind");
exec_name_list.push_back("break");
exec_name_list.push_back("builtin");
exec_name_list.push_back("caller");
exec_name_list.push_back("case");
exec_name_list.push_back("cd");
exec_name_list.push_back("command");
exec_name_list.push_back("continue");
exec_name_list.push_back("coproc");
exec_name_list.push_back("dirs");
exec_name_list.push_back("echo");
exec_name_list.push_back("elif");
exec_name_list.push_back("enable");
exec_name_list.push_back("eval");
exec_name_list.push_back("exec");
exec_name_list.push_back("exit");
exec_name_list.push_back("export");
exec_name_list.push_back("for");
exec_name_list.push_back("function");
exec_name_list.push_back("getopts");
exec_name_list.push_back("hash");
exec_name_list.push_back("if");
exec_name_list.push_back("let");
exec_name_list.push_back("mapfile");
exec_name_list.push_back("popd");
exec_name_list.push_back("printf");
exec_name_list.push_back("pushd");
exec_name_list.push_back("pwd");
exec_name_list.push_back("read");
exec_name_list.push_back("readarray");
exec_name_list.push_back("readonly");
exec_name_list.push_back("return");
exec_name_list.push_back("select");
exec_name_list.push_back("set");
exec_name_list.push_back("shift");
exec_name_list.push_back("source");
exec_name_list.push_back("test");
exec_name_list.push_back("time");
exec_name_list.push_back("times");
exec_name_list.push_back("trap");
exec_name_list.push_back("ulimit");
exec_name_list.push_back("umask");
exec_name_list.push_back("unalias");
exec_name_list.push_back("unset");
exec_name_list.push_back("until");
exec_name_list.push_back("while");
cmplx_calc_list.push_back("%");
cmplx_calc_list.push_back("^");
cmplx_calc_list.push_back("++");
cmplx_calc_list.push_back("+");
cmplx_calc_list.push_back("--");
cmplx_calc_list.push_back("-");
cmplx_calc_list.push_back("*");
cmplx_calc_list.push_back("/");
cmplx_cond_list.push_back("case");
cmplx_cond_list.push_back("elif");
cmplx_cond_list.push_back("if");
cmplx_cond_list.push_back("for");
cmplx_cond_list.push_back("select");
cmplx_cond_list.push_back("until");
cmplx_cond_list.push_back("while");
cmplx_logic_list.push_back("&&");
cmplx_logic_list.push_back("||");
cmplx_logic_list.push_back("==");
cmplx_logic_list.push_back("!");
cmplx_logic_list.push_back("~");
cmplx_logic_list.push_back(">");
cmplx_logic_list.push_back("<");
cmplx_logic_list.push_back(">=");
cmplx_logic_list.push_back("=<");
cmplx_logic_list.push_back("-lt");
cmplx_logic_list.push_back("-gt");
cmplx_logic_list.push_back("-ge");
cmplx_logic_list.push_back("-le");
cmplx_logic_list.push_back("-eq");
cmplx_logic_list.push_back("-ne");
cmplx_assign_list.push_back("=");
cmplx_cyclomatic_list.push_back("if");
cmplx_cyclomatic_list.push_back("for");
//cmplx_cyclomatic_list.push_back("case");
cmplx_cyclomatic_list.push_back("elif");
cmplx_cyclomatic_list.push_back("while");
//cmplx_cyclomatic_list.push_back("else");
cmplx_cyclomatic_list.push_back("until");
cmplx_cyclomatic_list.push_back(";;");
cmplx_cyclomatic_logic_list.push_back("&&");
cmplx_cyclomatic_logic_list.push_back("||");
cmplx_cyclomatic_case_list.push_back(";;");
cmplx_cyclomatic_switch_list.push_back("case");
}
/*!
* Perform preprocessing of file lines before counting.
*
* \param fmap list of file lines
*
* \return method status
*/
int CBashCounter::PreCountProcess(filemap* fmap)
{
filemap::iterator fit;
for (fit = fmap->begin(); fit != fmap->end(); fit++)
{
if (fit->line.empty())
continue;
for (size_t i = fit->line.length() - 1; i > 0; i--)
{
// replace $# and ${# with $ to avoid determination of a comment
if (fit->line[i] == '#' && (fit->line[i-1] == '$' || fit->line[i-1] == '{'))
fit->line[i] = '$';
}
}
return 0;
}
/*!
* Processes physical and logical lines according to language specific rules.
* NOTE: all the blank lines +
* whole line comments +
* lines with compiler directives
* should have been blanked from filemap by previous processing
* before reaching this function
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CBashCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak)
{
filemap::iterator fit, fitbak;
string line, lineBak;
bool data_continue = false;
string strLSLOC = "";
string strLSLOCBak = "";
string str;
unsigned int phys_exec_lines = 0;
unsigned int phys_data_lines = 0;
unsigned int temp_lines = 0;
unsigned int cnt = 0;
StringVector loopLevel;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
for (fit = fmap->begin(), fitbak = fmapBak->begin(); fit != fmap->end(); fit++, fitbak++)
{
line = fit->line;
lineBak = fitbak->line;
// do not process blank lines (blank_line/comment_line/directive)
if (!CUtil::CheckBlank(line))
{
// process logical SLOC
LSLOC(result, line, fit->lineNumber, lineBak, strLSLOC, strLSLOCBak, data_continue,
temp_lines, phys_exec_lines, phys_data_lines, loopLevel);
if (print_cmplx)
{
cnt = 0;
CUtil::CountTally(line, exec_name_list, cnt, 1, exclude, "", "", &result->exec_name_count);
}
// update physical SLOC lines
result->exec_lines[PHY] += phys_exec_lines;
phys_exec_lines = 0;
result->data_lines[PHY] += phys_data_lines;
phys_data_lines = 0;
}
}
return 1;
}
/*!
* Extracts and stores logical lines of code.
* Determines and extract logical SLOC to place in the result variable
* using addSLOC function. Each time the addSLOC function is called,
* a new logical SLOC is added. This function assumes that the directive
* is handled before it is called.
*
* \param result counter results
* \param line processed physical line of code
* \param lineBak original physical line of code
* \param strLSLOC processed logical string
* \param strLSLOCBak original logical string
* \param data_continue continuation of a data declaration line
* \param temp_lines tracks physical line count
* \param phys_exec_lines number of physical executable lines
* \param phys_data_lines number of physical data lines
* \param loopLevel nested loop level
*/
void CBashCounter::LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
bool &data_continue, unsigned int &temp_lines, unsigned int &phys_exec_lines,
unsigned int &phys_data_lines, StringVector &loopLevel)
{
size_t start, end;
size_t i = 0, m, strSize;
bool trunc_flag = false, found;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
string str, spc;
unsigned int cnt = 0;
string tmp = CUtil::TrimString(line);
string tmpBak = CUtil::TrimString(lineBak);
start = 0;
// skip whole line '{' or '}'
if (tmp == "{" || tmp == "}")
{
strLSLOC = strLSLOCBak = "";
phys_exec_lines++;
temp_lines = 0;
return;
}
// trim trailing '{'
if (tmp[tmp.length() - 1] == '{')
{
tmp = CUtil::TrimString(tmp.substr(0, tmp.length() - 1));
tmpBak = CUtil::TrimString(tmpBak.substr(0, tmpBak.length() - 1));
}
// there may be more than 1 logical SLOC in this line
while (start < tmp.length())
{
// check for semicolon to denote end of SLOC
end = tmp.find(";", start);
if (end != string::npos)
{
// handle empty statement
if (CUtil::TrimString(tmp.substr(start, end - start + 1)) == ";")
{
start = end + 1;
strLSLOC = strLSLOCBak = "";
temp_lines = 0;
if (tmp == ";")
phys_exec_lines++;
continue;
}
// handle for (( ; ; ))
i = CUtil::FindKeyword(tmp, "for", start, end);
if (i != string::npos)
{
i += 3;
i = tmp.find("((", i);
if (i != string::npos && i < end)
{
i += 2;
i = tmp.find("))", i);
if (i != string::npos)
{
i += 2;
end = tmp.find(";", i);
if (end == string::npos)
end = tmp.length() - 1;
}
else
end = tmp.length() - 1;
}
}
// handle case ';;' or ';&' or ';;&'
if (end < tmp.length() - 1)
{
if (tmp[end + 1] == ';' || tmp[end + 1] == '&')
end++;
if (end < tmp.length() - 2 && tmp[end + 2] == '&')
end++;
}
}
else
end = tmp.length() - 1;
// process nested loops
if (print_cmplx)
{
str = CUtil::TrimString(tmp.substr(start, end - start + 1));
if (CUtil::FindKeyword(str, "for") != string::npos
|| CUtil::FindKeyword(str, "while") != string::npos
|| CUtil::FindKeyword(str, "until")!= string::npos
|| CUtil::FindKeyword(str, "select")!= string::npos)
{
if (CUtil::FindKeyword(str, "for") != string::npos)
loopLevel.push_back("for");
else if (CUtil::FindKeyword(str, "while")!= string::npos)
loopLevel.push_back("while");
else if (CUtil::FindKeyword(str, "until") != string::npos)
loopLevel.push_back("until");
else if (CUtil::FindKeyword(str, "select") != string::npos)
loopLevel.push_back("");
// record nested loop level
if (CUtil::FindKeyword(str, "select") == string::npos)
{
unsigned int loopCnt = 0;
for (StringVector::iterator lit = loopLevel.begin(); lit < loopLevel.end(); lit++)
{
if ((*lit) != "")
loopCnt++;
}
if ((unsigned int)result->cmplx_nestloop_count.size() < loopCnt)
result->cmplx_nestloop_count.push_back(1);
else
result->cmplx_nestloop_count[loopCnt-1]++;
}
}
if (CUtil::FindKeyword(str, "done") != string::npos && loopLevel.size() > 0)
loopLevel.pop_back();
}
// check for line containing excluded keywords
for (StringVector::iterator it = exclude_keywords.begin(); it != exclude_keywords.end(); it++)
{
i = CUtil::FindKeyword(tmp, (*it), start, end);
if (i != string::npos)
{
// strip specified keyword and skip if empty
start = i + (*it).length();
if (CUtil::CheckBlank(CUtil::TrimString(tmp.substr(start, end - start))))
start = end + 1;
break;
}
}
if (start > end)
{
if (temp_lines == 0 && phys_data_lines == 0 && phys_exec_lines == 0)
phys_exec_lines = 1;
continue;
}
// check for continuation words
found = false;
if (tmp[end] == ';')
str = CUtil::TrimString(tmp.substr(start, end - start));
else
str = CUtil::TrimString(tmp.substr(start, end - start + 1));
for (StringVector::iterator it = continue_keywords.begin(); it != continue_keywords.end(); it++)
{
if (str == (*it))
{
found = true;
strLSLOC += str + " ";
strLSLOCBak += str + " ";
start = end + 1;
if (temp_lines == 0 && phys_data_lines == 0 && phys_exec_lines == 0)
phys_exec_lines = 1;
temp_lines = 0;
}
}
if (found)
continue;
// check for line continuation
if (tmp[end] == '\\')
{
// strip off trailing (\)
strSize = CUtil::TruncateLine(end - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
spc = "";
str = tmp.substr(start, strSize);
for (m = str.length() - 1; m > 0; m--)
{
if (str[m] == ' ')
spc += " ";
else
break;
}
if (m == 0)
{
if (str[0] == ' ')
spc += " ";
}
strLSLOC += CUtil::TrimString(tmp.substr(start, strSize)) + spc;
strLSLOCBak += CUtil::TrimString(tmpBak.substr(start, strSize)) + spc;
}
start = end + 1;
// make sure that we are not beginning to process a new data line
cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", NULL);
if (cnt > 0)
data_continue = true;
if (data_continue == true)
temp_lines++;
if (temp_lines == 0 && phys_data_lines == 0 && phys_exec_lines == 0)
phys_exec_lines = 1;
}
else
{
// save LSLOC
if (tmp[end] == ';')
{
// don't trim if ';;'
if (tmp.length() > 1 && tmp[end - 1] == ';')
strSize = CUtil::TruncateLine(end - start + 1, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
else
strSize = CUtil::TruncateLine(end - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
}
else
strSize = CUtil::TruncateLine(end - start + 1, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += CUtil::TrimString(tmp.substr(start, strSize));
strLSLOCBak += CUtil::TrimString(tmpBak.substr(start, strSize));
}
start = end + 1;
if (strLSLOCBak.length() > 0)
{
if (result->addSLOC(strLSLOCBak, lineNumber, trunc_flag))
{
// add a logical SLOC
cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", &result->data_name_count);
temp_lines++;
if (data_continue == true || cnt > 0)
{
result->data_lines[LOG]++;
phys_data_lines = temp_lines;
}
else
{
result->exec_lines[LOG]++;
phys_exec_lines = temp_lines;
}
}
else if (data_continue == true)
phys_data_lines = temp_lines;
else
phys_exec_lines = temp_lines;
}
data_continue = false;
temp_lines = 0;
strLSLOC = strLSLOCBak = "";
}
}
}
/*!
* Parses lines for function/method names.
*
* \param line line to be processed
* \param lastline last line processed
* \param functionStack stack of functions
* \param functionName function name found
* \param functionCount function count found
*
* \return 1 if function name is found
*/
int CBashCounter::ParseFunctionName(const string &line, string &lastline,
filemap &functionStack, string &functionName, unsigned int &functionCount)
{
string tline, str;
size_t i, idx, tidx, cnt;
unsigned int fcnt;
tline = CUtil::TrimString(line);
idx = tline.find('{');
if (idx != string::npos)
{
// check whether it is at first index, if yes then function name is at above line
if (idx == 0)
{
lineElement element(++functionCount, lastline);
functionStack.push_back(element);
lastline.erase();
}
else
{
str = tline.substr(0, idx);
if (str.find('(') != string::npos && str[0] != '(')
lastline = str;
else
lastline += " " + str;
lineElement element(++functionCount, CUtil::TrimString(lastline));
functionStack.push_back(element);
lastline.erase();
}
}
else if (tline.length() > 0 && tline[tline.length() - 1] != ';' &&
lastline.length() > 0 && lastline[lastline.length() - 1] != ';')
{
// append until all parenthesis are closed
tidx = lastline.find('(');
if (tidx != string::npos)
{
cnt = 1;
while (tidx != string::npos)
{
tidx = lastline.find('(', tidx + 1);
if (tidx != string::npos)
cnt++;
}
tidx = lastline.find(')');
while (tidx != string::npos)
{
cnt++;
tidx = lastline.find(')', tidx + 1);
}
if (cnt % 2 != 0)
lastline += " " + tline;
else
lastline = tline;
}
else
lastline = tline;
}
else
lastline = tline;
idx = line.find('}');
if (idx != string::npos && !functionStack.empty())
{
str = functionStack.back().line;
fcnt = functionStack.back().lineNumber;
functionStack.pop_back();
idx = CUtil::FindKeyword(str, "sub");
if (idx != string::npos && idx + 4 < str.length())
{
functionName = CUtil::ClearRedundantSpaces(str.substr(idx + 4));
functionCount = fcnt;
lastline.erase();
return 1;
}
lastline.erase();
}
// check stack for any "sub"
idx = string::npos;
if (!functionStack.empty())
{
for (i = 0; i < functionStack.size(); i++)
{
idx = CUtil::FindKeyword(functionStack[i].line, "sub");
if (idx != string::npos)
break;
}
}
if (idx == string::npos)
{
// dealing with some code out of any subroutines, it a "main" code
return 2;
}
return 0;
}
//Writen by Rujun Ma 11.28.16
/*!
* Counts the number of comment lines, removes comments, and
* replaces quoted strings by special chars, e.g., $
* All arguments are modified by the method.
* Special processing for """ and ''' which can be multi-line literal
* or a multi-line comment if it stands alone.
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CBashCounter::CountCommentsSLOC(filemap* fmap, results* result, filemap *fmapBak)
{
if (BlockCommentStart.empty() && LineCommentStart.empty())
return 0;
if (classtype == UNKNOWN || classtype == DATAFILE)
return 0;
bool contd = false;
bool contd_nextline;
int comment_type = 0;
/*
comment_type:
0 : not a comment
1 : line comment, whole line
2 : line comment, embedded
3 : block comment, undecided
4 : block comment, embedded
*/
size_t idx_start, idx_end, comment_start;
size_t quote_idx_start;
string curBlckCmtStart, curBlckCmtEnd, tmp;
string CurrentQuoteEnd = "";
bool quote_contd = false;
filemap::iterator itfmBak = fmapBak->begin();
quote_idx_start = 0;
for (filemap::iterator iter = fmap->begin(); iter != fmap->end(); iter++, itfmBak++)
{
contd_nextline = false;
quote_idx_start = 0;
idx_start = 0;
if (CUtil::CheckBlank(iter->line))
continue;
//this should be counted as a compiler directive, not a comment
if (iter->line.size() > 2 && iter->line.substr(0, 2) == "#!") {
if (iter->line.find('/') != std::string::npos) continue;
}
if (quote_contd)
{
// Replace quote until next character
ReplaceQuote(iter->line, quote_idx_start, quote_contd, CurrentQuoteEnd);
if (quote_contd)
continue;
}
if (contd)
comment_type = 3;
while (!contd_nextline && idx_start < iter->line.length())
{
// need to handle multiple quote chars in some languages, both " and ' may be accepted
quote_idx_start = FindQuote(iter->line, QuoteStart, quote_idx_start, QuoteEscapeFront);
comment_start = idx_start;
if (!contd)
{
FindCommentStart(iter->line, comment_start, comment_type, curBlckCmtStart, curBlckCmtEnd);
if (comment_start != string::npos && comment_type > 2)
{
// python: check whether this is a multi-line literal or a block comment
tmp = CUtil::TrimString(iter->line, -1);
if (iter->line.length() - tmp.length() != comment_start)
{
quote_idx_start = comment_start;
comment_start = string::npos;
}
}
}
if (comment_start == string::npos && quote_idx_start == string::npos)
break;
if (comment_start != string::npos)
idx_start = comment_start;
// if found quote before comment, e.g., "this is quote");//comment
if (quote_idx_start != string::npos && (comment_start == string::npos || quote_idx_start < comment_start))
{
ReplaceQuote(iter->line, quote_idx_start, quote_contd, CurrentQuoteEnd);
if (quote_idx_start > idx_start && quote_idx_start != iter->line.length())
{
// comment delimiter inside quote
idx_start = quote_idx_start;
continue;
}
}
else if (comment_start != string::npos)
{
// comment delimiter starts first
switch (comment_type)
{
case 1: // line comment, definitely whole line
iter->line = "";
itfmBak->line = "";
result->comment_lines++;
contd_nextline = true;
break;
case 2: // line comment, possibly embedded
iter->line = iter->line.substr(0, idx_start);
itfmBak->line = itfmBak->line.substr(0, idx_start);
// trim trailing space
iter->line = CUtil::TrimString(iter->line, 1);
itfmBak->line = CUtil::TrimString(itfmBak->line, 1);
if (iter->line.empty())
result->comment_lines++; // whole line
else
result->e_comm_lines++; // embedded
contd_nextline = true;
break;
case 3: // block comment
case 4:
if (contd)
idx_end = iter->line.find(curBlckCmtEnd);
else
idx_end = iter->line.find(curBlckCmtEnd, idx_start + curBlckCmtStart.length());
if (idx_end == string::npos)
{
if (comment_type == 3)
{
iter->line = "";
itfmBak->line = "";
result->comment_lines++;
}
else if (comment_type == 4)
{
iter->line = iter->line.substr(0, idx_start);
itfmBak->line = itfmBak->line.substr(0, idx_start);
// trim trailing space
iter->line = CUtil::TrimString(iter->line, 1);
itfmBak->line = CUtil::TrimString(itfmBak->line, 1);
if (iter->line.empty())
result->comment_lines++; // whole line
else
result->e_comm_lines++; // embedded
}
contd = true;
contd_nextline = true;
break;
}
else
{
contd = false;
iter->line.erase(idx_start, idx_end - idx_start + curBlckCmtEnd.length());
itfmBak->line.erase(idx_start, idx_end - idx_start + curBlckCmtEnd.length());
if (iter->line.empty())
result->comment_lines++;
else
{
// trim trailing space
iter->line = CUtil::TrimString(iter->line, 1);
itfmBak->line = CUtil::TrimString(itfmBak->line, 1);
if (iter->line.empty())
result->comment_lines++; // whole line
else
result->e_comm_lines++; // embedded
}
// quote chars found may be erased as it is inside comment
quote_idx_start = idx_start;
}
break;
default:
cout << "Error in CountCommentsSLOC()" << endl;
break;
}
}
}
}
return 1;
}
/*!
* Replaces up to ONE quoted string inside a string starting at idx_start.
* Uses a string instead of a character to allow processing multi-line
* literals """ and '''.
*
* \param strline string to be processed
* \param idx_start index of line character to start search
* \param contd specifies the quote string is continued from the previous line
* \param CurrentQuoteEnd end quote string of the current status
*
* \return method status
*/
int CBashCounter::ReplaceQuote(string &strline, size_t &idx_start, bool &contd, string &CurrentQuoteEnd)
{
size_t idx_end, idx_quote;
if (contd)
{
// python: use string instead of character to check for """ and '''
idx_start = 0;
if (strline.length() >= CurrentQuoteEnd.length() &&
strline.substr(0, CurrentQuoteEnd.length()) == CurrentQuoteEnd)
{
idx_start = CurrentQuoteEnd.length();
contd = false;
return 1;
}
strline[0] = '$';
}
else
{
// handle two quote chars in some languages, both " and ' may be accepted
idx_start = FindQuote(strline, QuoteStart, idx_start, QuoteEscapeFront);
if (idx_start != string::npos)
{
idx_quote = QuoteStart.find_first_of(strline[idx_start]);
CurrentQuoteEnd = QuoteEnd[idx_quote];
// python: check for """ or '''
if (strline.length() >= idx_start + 3)
{
if (CurrentQuoteEnd == "\"")
{
if (strline.substr(idx_start, 3) == "\"\"\"")
CurrentQuoteEnd = "\"\"\"";
}
else if (CurrentQuoteEnd == "'")
{
if (strline.substr(idx_start, 3) == "'''")
CurrentQuoteEnd = "'''";
}
}
}
else
{
idx_start = strline.length();
return 0;
}
}
// python: handle """ and '''
if (CurrentQuoteEnd.length() == 3)
{
if (idx_start + 3 >= strline.length())
idx_end = string::npos;
else
{
idx_end = strline.find(CurrentQuoteEnd, idx_start + 3);
if (idx_end != string::npos)
idx_end += 2; // shift to last quote character
}
}
else
idx_end = CUtil::FindCharAvoidEscape(strline, CurrentQuoteEnd[0], idx_start + 1, QuoteEscapeFront);
if (idx_end == string::npos)
{
idx_end = strline.length() - 1;
strline.replace(idx_start + 1, idx_end - idx_start, idx_end - idx_start, '$');
contd = true;
idx_start = idx_end + 1;
}
else
{
if (CurrentQuoteEnd.length() != 3 && (QuoteEscapeRear) && (strline.length() > idx_end + 1) && (strline[idx_end + 1] == QuoteEscapeRear))
{
strline[idx_end] = '$';
strline[idx_end + 1] = '$';
}
else
{
contd = false;
strline.replace(idx_start + 1, idx_end - idx_start - 1, idx_end - idx_start - 1, '$');
idx_start = idx_end + 1;
}
}
return 1;
}
/*!
* Counts directive lines of code.
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CBashCounter::CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapBak)
{
bool contd = false, trunc_flag = false;
size_t idx, strSize;
unsigned int cnt = 0;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
string strDirLine = "";
filemap::iterator itfmBak = fmapBak->begin();
for (filemap::iterator iter = fmap->begin(); iter != fmap->end(); iter++, itfmBak++)
{
if (CUtil::CheckBlank(iter->line))
continue;
size_t lineNumber = iter->lineNumber;
if (print_cmplx)
{
cnt = 0;
CUtil::CountTally(" " + iter->line, directive, cnt, 1, exclude, "", "", &result->directive_count);
}
if (!contd)
{
// if not a continuation of a previous directive
for (vector<string>::iterator viter = directive.begin(); viter != directive.end(); viter++)
{
if ((idx = iter->line.find((*viter), 0)) != string::npos && idx == 0)
{
contd = true;
break;
}
}
if (contd)
{
strSize = CUtil::TruncateLine(itfmBak->line.length(), 0, this->lsloc_truncate, trunc_flag);
if (strSize > 0)
strDirLine = itfmBak->line.substr(0, strSize);
result->directive_lines[PHY]++;
}
}
else
{
// continuation of a previous directive
strSize = CUtil::TruncateLine(itfmBak->line.length(), strDirLine.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
strDirLine += "\n" + itfmBak->line.substr(0, strSize);
result->directive_lines[PHY]++;
}
if (contd)
{
// drop continuation symbol
if (strDirLine[strDirLine.length() - 1] == '\\')
strDirLine = strDirLine.substr(0, strDirLine.length() - 1);
// if a directive or continuation of a directive (no continuation symbol found)
if (iter->line[iter->line.length() - 1] != '_')
{
contd = false;
if (result->addSLOC(strDirLine, lineNumber, trunc_flag))
result->directive_lines[LOG]++;
}
iter->line = "";
}
}
return 1;
}

55
src/CBashCounter.h

@ -0,0 +1,55 @@
//! Code counter class definition for the Bash shell script language.
/*!
* \file CBashCounter.h
*
* This file contains the code counter class definition for the Bash shell script language.
* This also includes the Korn shell language.
*/
#ifndef CBashCounter_h
#define CBashCounter_h
#include "CCodeCounter.h"
//! Bash shell script code counter class.
/*!
* \class CBashCounter
*
* Defines the Bash shell script code counter class.
*/
class CBashCounter : public CCodeCounter
{
public:
CBashCounter();
protected:
virtual int PreCountProcess(filemap* fmap);
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak = NULL);
//Added by Rujun Ma for BashCounter fix. 11.27.16
//changes maade by Nikhila Banukumar
using CCodeCounter::ReplaceQuote;
virtual int ReplaceQuote(string &strline, size_t &idx_start, bool &contd, string &CurrentQuoteEnd);
virtual int CountCommentsSLOC(filemap* fmap, results* result, filemap* fmapBak = NULL);
virtual int CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapBak = NULL);
void LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC,
string &strLSLOCBak, bool &data_continue, unsigned int &temp_lines, unsigned int &phys_exec_lines,
unsigned int &phys_data_lines, StringVector &loopLevel);
int ParseFunctionName(const string &line, string &lastline, filemap &functionStack,
string &functionName, unsigned int &functionCount);
StringVector continue_keywords; //!< List of keywords to continue to next line
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CBashCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CBashCounter(const CBashCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CBashCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CBashCounter operator=(const CBashCounter); // Declare without implementation
};
#endif

904
src/CBatchCounter.cpp

@ -0,0 +1,904 @@
//! Code counter class methods for the DOS Batch language.
/*!
* \file CBatchCounter.cpp
*
* This file contains the code counter class methods for the DOS Batch language.
* This also includes the MS-DOS commands.*/
#include <string.h>
#include "CBatchCounter.h"
//#include "MainObject.h"
// changed calling tolower() to use lowerChars array
extern unsigned char lowerChars[256];
/*!
* Constructs a CBatchCounter object.
*/
CBatchCounter::CBatchCounter ()
{
classtype = BATCH;
language_name = "DOS_Batch";
//Modification: 11.2016 Ext-4
file_extension = CUtil::getExtensionsToLanguage("DOS_Batch", file_extension);
//file_extension.push_back(".bat");
QuoteStart = "\"'";
QuoteEnd = "\"'";
QuoteEscapeFront = '\\';
ContinueLine = "^";
//Comments in .bat
LineCommentStart.push_back("rem");
LineCommentStart.push_back("::");
continue_keywords.push_back("else");
//commands in .bat
exec_name_list.push_back("ansi.sys");
exec_name_list.push_back("append");
exec_name_list.push_back("arp");
exec_name_list.push_back("assign");
exec_name_list.push_back("assoc");
exec_name_list.push_back("at");
exec_name_list.push_back("atmadm");
exec_name_list.push_back("attrib");
exec_name_list.push_back("backup");
exec_name_list.push_back("batch");
exec_name_list.push_back("bootcfg");
exec_name_list.push_back("bootsect");
exec_name_list.push_back("break");
exec_name_list.push_back("cacls");
exec_name_list.push_back("call");
exec_name_list.push_back("cd");
exec_name_list.push_back("chcp");
exec_name_list.push_back("chdir");
exec_name_list.push_back("chkdsk");
exec_name_list.push_back("chkntfs");
exec_name_list.push_back("choice");
exec_name_list.push_back("cipher");
exec_name_list.push_back("cls");
exec_name_list.push_back("cmd");
exec_name_list.push_back("color");
exec_name_list.push_back("command");
exec_name_list.push_back("comp");
exec_name_list.push_back("compact");
exec_name_list.push_back("control");
exec_name_list.push_back("convert");
exec_name_list.push_back("copy");
exec_name_list.push_back("ctty");
exec_name_list.push_back("date");
exec_name_list.push_back("debug");
exec_name_list.push_back("defrag");
exec_name_list.push_back("del");
exec_name_list.push_back("delete");
exec_name_list.push_back("deltree");
exec_name_list.push_back("dir");
exec_name_list.push_back("disable");
exec_name_list.push_back("diskcomp");
exec_name_list.push_back("diskcopy");
exec_name_list.push_back("diskpart");
exec_name_list.push_back("doskey");
exec_name_list.push_back("dosshell");
exec_name_list.push_back("drivparm");
exec_name_list.push_back("echo");
exec_name_list.push_back("edit");
exec_name_list.push_back("edlin");
exec_name_list.push_back("emm386");
exec_name_list.push_back("enable");
exec_name_list.push_back("endlocal");
exec_name_list.push_back("erase");
exec_name_list.push_back("exit");
exec_name_list.push_back("expand");
exec_name_list.push_back("extract");
exec_name_list.push_back("fasthelp");
exec_name_list.push_back("fc");
exec_name_list.push_back("fdisk");
exec_name_list.push_back("find");
exec_name_list.push_back("findstr");
exec_name_list.push_back("fixboot");
exec_name_list.push_back("fixmbr");
exec_name_list.push_back("for");
exec_name_list.push_back("forfiles");
exec_name_list.push_back("format");
exec_name_list.push_back("ftp");
exec_name_list.push_back("fType");
exec_name_list.push_back("goto");
exec_name_list.push_back("gpupdate");
exec_name_list.push_back("graftabl");
exec_name_list.push_back("help");
exec_name_list.push_back("himem");
exec_name_list.push_back("sys");
exec_name_list.push_back("hostname");
exec_name_list.push_back("if");
exec_name_list.push_back("ifshlp");
exec_name_list.push_back("sys");
exec_name_list.push_back("ipconfig");
exec_name_list.push_back("keyb");
exec_name_list.push_back("label");
exec_name_list.push_back("lh");
exec_name_list.push_back("listsvc");
exec_name_list.push_back("loadfix");
exec_name_list.push_back("loadhigh");
exec_name_list.push_back("lock");
exec_name_list.push_back("logoff");
exec_name_list.push_back("logon");
exec_name_list.push_back("map");
exec_name_list.push_back("md");
exec_name_list.push_back("mem");
exec_name_list.push_back("mkdir");
exec_name_list.push_back("mode");
exec_name_list.push_back("more");
exec_name_list.push_back("move");
exec_name_list.push_back("msav");
exec_name_list.push_back("msbackup");
exec_name_list.push_back("msd");
exec_name_list.push_back("mscdex");
exec_name_list.push_back("mwbackup");
exec_name_list.push_back("nbtstat");
exec_name_list.push_back("net");
exec_name_list.push_back("netsh");
exec_name_list.push_back("netstat");
exec_name_list.push_back("nlsfunc");
exec_name_list.push_back("nslookup");
exec_name_list.push_back("path");
exec_name_list.push_back("pathping");
exec_name_list.push_back("pause");
exec_name_list.push_back("ping");
exec_name_list.push_back("popd");
exec_name_list.push_back("power");
exec_name_list.push_back("print");
exec_name_list.push_back("prompt");
exec_name_list.push_back("pushd");
exec_name_list.push_back("qbasic");
exec_name_list.push_back("rd");
exec_name_list.push_back("reg");
exec_name_list.push_back("ren");
exec_name_list.push_back("rename");
exec_name_list.push_back("rmdir");
exec_name_list.push_back("robocopy");
exec_name_list.push_back("route");
exec_name_list.push_back("runas");
exec_name_list.push_back("scandisk");
exec_name_list.push_back("scanreg");
exec_name_list.push_back("set");
exec_name_list.push_back("setlocal");
exec_name_list.push_back("setver");
exec_name_list.push_back("sfc");
exec_name_list.push_back("share");
exec_name_list.push_back("shift");
exec_name_list.push_back("shutdown");
exec_name_list.push_back("smartdrv");
exec_name_list.push_back("sort");
exec_name_list.push_back("start");
exec_name_list.push_back("subst");
exec_name_list.push_back("switches");
exec_name_list.push_back("sys");
exec_name_list.push_back("systeminfo");
exec_name_list.push_back("systemroot");
exec_name_list.push_back("taskkill");
exec_name_list.push_back("tasklist");
exec_name_list.push_back("telnet");
exec_name_list.push_back("time");
exec_name_list.push_back("title");
exec_name_list.push_back("tracert");
exec_name_list.push_back("tree");
exec_name_list.push_back("tskill");
exec_name_list.push_back("Type");
exec_name_list.push_back("undelete");
exec_name_list.push_back("unformat");
exec_name_list.push_back("unlock");
exec_name_list.push_back("ver");
exec_name_list.push_back("verify");
exec_name_list.push_back("vol");
exec_name_list.push_back("wmic");
exec_name_list.push_back("xcopy");
//arithmetic operations in .bat
cmplx_calc_list.push_back("%");
cmplx_calc_list.push_back("^");
cmplx_calc_list.push_back("+");
cmplx_calc_list.push_back("-");
cmplx_calc_list.push_back("/");
cmplx_calc_list.push_back("*");
cmplx_calc_list.push_back("<<");
cmplx_calc_list.push_back(">>");
cmplx_calc_list.push_back("&");
cmplx_calc_list.push_back("|");
//complex commands in .bat
cmplx_cond_list.push_back("for");
cmplx_cond_list.push_back("if");
cmplx_cond_list.push_back("choice");
//logical operations in .bat
cmplx_logic_list.push_back("&&");
cmplx_logic_list.push_back("||");
cmplx_logic_list.push_back("==");
cmplx_logic_list.push_back("equ");
cmplx_logic_list.push_back("neq");
cmplx_logic_list.push_back("lss");
cmplx_logic_list.push_back("leq");
cmplx_logic_list.push_back("gtr");
cmplx_logic_list.push_back("geq");
cmplx_assign_list.push_back("=");
// cyclometic complexity
cmplx_cyclomatic_list.push_back("if");
cmplx_cyclomatic_list.push_back("while");
cmplx_cyclomatic_list.push_back("for");
cmplx_cyclomatic_list.push_back("unless");
cmplx_cyclomatic_logic_list.push_back("&&");
cmplx_cyclomatic_logic_list.push_back("||");
//there is no keyword "case" in DOS_Batch, so no CC3.
}
/*!
* Perform preprocessing of file lines before counting.
*
* \param fmap list of file lines
*
* \return method status
*/
int CBatchCounter::PreCountProcess(filemap* fmap)
{
filemap::iterator fit;
for (fit = fmap->begin(); fit != fmap->end(); fit++)
{
if (fit->line.empty())
continue;
for (size_t i = fit->line.length() - 1; i > 0; i--)
{
// to lowercase
fit->line[i] = (char)lowerChars[ TL_ARR( fit->line[i] ) ];
fit->line[i-1] = (char)lowerChars[ TL_ARR( fit->line[i-1] ) ];
// replace with space
if (fit->line[i] == '(' || fit->line[i] == ')' || fit->line[i] == '\'' || fit->line[i] == '.' || fit->line[i] == '@') {
fit->line[i] = ' ';
}
if (fit->line[i-1] ==')' || fit->line[i-1] =='(' || fit->line[i-1] == '\'' || fit->line[i-1] == '.' || fit->line[i-1] == '@') {
fit->line[i-1] = ' ';
}
}
if (CUtil::CheckBlank(fit->line))
fit->line = "$";
//ignore words after keyword "echo"
/*int idx = CUtil::FindKeyword(fit->line, "echo");*/
size_t idx = CUtil::FindKeyword(fit->line, "echo"); // warning fix
if(idx != string::npos) {
for (size_t i = idx + 4; i < fit->line.length(); i++)
{
fit->line[i] = '$';
}
}
}
return 0;
}
/*!
* Processes physical and logical lines according to language specific rules.
* NOTE: all the blank lines +
* whole line comments +
* lines with compiler directives
* should have been blanked from filemap by previous processing
* before reaching this function
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CBatchCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak)
{
filemap::iterator fit, fitbak;
string line, lineBak;
bool data_continue = false;
string strLSLOC = "";
string strLSLOCBak = "";
string str;
unsigned int phys_exec_lines = 0;
unsigned int phys_data_lines = 0;
unsigned int temp_lines = 0;
unsigned int cnt = 0;
//StringVector loopLevel; warning fix
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
for (fit = fmap->begin(), fitbak = fmapBak->begin(); fit != fmap->end(); fit++, fitbak++)
{
line = fit->line;
lineBak = fitbak->line;
// do not process blank lines (blank_line/comment_line/directive)
if (!CUtil::CheckBlank(line))
{
// process logical SLOC
LSLOC(result, line, fit->lineNumber, lineBak, strLSLOC, strLSLOCBak, data_continue,
temp_lines, phys_exec_lines, phys_data_lines/*, loopLevel*/); //warning fix
if (print_cmplx)
{
cnt = 0;
CUtil::CountTally(line, exec_name_list, cnt, 1, exclude, "", "", &result->exec_name_count);
}
// update physical SLOC lines
result->exec_lines[PHY] += phys_exec_lines;
phys_exec_lines = 0;
result->data_lines[PHY] += phys_data_lines;
phys_data_lines = 0;
}
}
return 1;
}
void CBatchCounter::LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
bool &data_continue, unsigned int &temp_lines, unsigned int &phys_exec_lines,
unsigned int &phys_data_lines/*, StringVector &loopLevel*/)// warning fix
{
size_t start, end;
size_t strSize;
bool trunc_flag = false;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
string str, spc;
unsigned int cnt = 0;
string tmp = CUtil::TrimString(line);
string tmpBak = CUtil::TrimString(lineBak);
start = 0;
end = tmp.length();
// skip whole line '(' or ')'
if (tmp == "(" || tmp == ")")
{
strLSLOC = strLSLOCBak = "";
phys_exec_lines++;
temp_lines = 0;
return;
}
// there may be more than 1 logical SLOC in this line
#ifdef _MSC_VER
char * context = NULL; // used for strtok_s( ) below
#else
//
#endif
bool has_for = false;
bool has_for_in = false;
while (start < tmp.length())
{
end = tmp.length();
if (start == 0) {
has_for = false;
has_for_in = false;
}
//std::cout << start <<"start\n";
// check if is a label
bool isLabel = false;
for (unsigned int i = 0; tmp[i] != '\0'; i++) {
if (tmp[i] == ' ') {
continue;
} else if (tmp[i] == ':') {
isLabel = true;
break;
} else {
break;
}
}
if(isLabel) {
strLSLOC = strLSLOCBak = "";
phys_exec_lines++;
temp_lines = 0;
return;
}
char * token = NULL;
// Allocate a char array that must be deleted later.
char* line = new char[end - start + 1];
#ifdef _MSC_VER
// Use more Secure C library API
strcpy_s( line, (end - start + 1) * sizeof(char), tmp.substr(start).c_str() );
#else
// Use older less Secure C library API
strcpy( line, tmp.substr(start).c_str() );
#endif
// check |, &
bool hasPipe = false;
size_t pipePos = 0;
bool hasAmp = false;
size_t ampPos = 0;
for (int i = 0; line[i] != '\0'; i++) {
if (line[i] == '|') {
if (!hasPipe) {
pipePos = (size_t)i;
}
hasPipe = true;
line[i] = ' ';
}
if (line[i] == '&') {
if (!hasAmp) {
ampPos = (size_t)i;
}
hasAmp = true;
line[i] = ' ';
}
}
#ifdef _MSC_VER
// Use more Secure C library API
token = strtok_s( line, " .@:", &context );
#else
// Use older less Secure C library API
token = strtok( line, " .@:" );
#endif
for (int i = 0; token[i] != '\0'; i++) {
token[i] = (char)lowerChars[ TL_ARR( token[i] ) ];
}
if (strcmp(token, "else") == 0)
{
#ifdef _MSC_VER
// Use more Secure C library API
token = strtok_s( NULL, " .@:", &context );
#else
// Use older less Secure C library API
token = strtok( NULL, " .@:" );
#endif
}
if (token == NULL) {
strLSLOC = strLSLOCBak = "";
phys_exec_lines++;
temp_lines = 0;
delete[] line;
return;
}
//first keyword
//std::cout << token << "TOKEN\n";
string firstWord(token);
firstWord = CUtil::ToLower(firstWord);
bool checkFirstWord = false;
for(std::vector<string>::iterator it = exec_name_list.begin(); it != exec_name_list.end(); ++it) {
if (*it == firstWord) {
checkFirstWord = true;
break;
}
}
if(!checkFirstWord) {
strLSLOC = strLSLOCBak = "";
phys_exec_lines++;
temp_lines = 0;
delete[] line;
return;
}
//if, for, choice as first word
bool isComplexWord = false;
bool isCall = false;
size_t nextKeyWordStart = (size_t)(-1);
bool isKeyWord = false;
bool hasElse = false;
char * nextToken = NULL;
size_t tmpNextKeyWordStart = (size_t)(-1);
size_t tmpEnd = (size_t)(-1);
for(std::vector<string>::iterator it = cmplx_cond_list.begin(); it != cmplx_cond_list.end(); ++it) {
if (*it == firstWord) {
isComplexWord = true;
break;
}
}
//for as first word
if (firstWord.compare("for") == 0) {
has_for = true;
}
//call as first word
if (firstWord.compare("call") == 0) {
isCall = true;
}
// go through the rest of words
#ifdef _MSC_VER
// Use more Secure C library API
nextToken = strtok_s( NULL, " .@:", &context );
#else
// Use older less Secure C library API
nextToken = strtok( NULL, " .@:" );
#endif
while (nextToken != NULL)
{
string nextWord(nextToken);
nextWord = CUtil::ToLower(nextWord);
if (has_for && nextWord.compare("in") == 0)
has_for_in = true;
if (nextWord.compare("else") == 0)
hasElse = true;
if (!isKeyWord)
{
for(std::vector<string>::iterator it2 = exec_name_list.begin(); it2 != exec_name_list.end(); ++it2)
{
if (*it2 == nextWord)
{
isKeyWord = true;
tmpNextKeyWordStart = CUtil::FindKeyword(CUtil::ToLower(tmp), nextWord, start + firstWord.length(), end);
//std::cout << tmpNextKeyWordStart << "NEXT_START\n";
tmpEnd = tmpNextKeyWordStart; // !!!!!
//std::cout << tmpEnd << "CURR_END\n";
break;
}
}
}
#ifdef _MSC_VER
// Use more Secure C library API
nextToken = strtok_s( NULL, " .@:", &context );
#else
// Use older less Secure C library API
nextToken = strtok( NULL, " .@:" );
#endif
}
if (isKeyWord)
{
//std::cout << pipePos << "pipePos\n";
if (hasPipe && pipePos >= tmpEnd)
hasPipe = false;
//std::cout << ampPos << "ampPos\n";
if (hasAmp && ampPos >= tmpEnd)
hasAmp = false;
}
else
{
hasPipe = false;
hasAmp = false;
}
if ((isComplexWord || isCall || hasElse || has_for_in || hasPipe || hasAmp) && isKeyWord) { // REMEMBER TO CHANGE THE SAME CODE BELOW
nextKeyWordStart = tmpNextKeyWordStart;
end = tmpEnd;
}
if (tmp[0] != '^') {
//std::cout << "2\n";
strSize = CUtil::TruncateLine(end - start + 1, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0) {
strLSLOC += CUtil::TrimString(tmp.substr(start, strSize));
strLSLOCBak += CUtil::TrimString(tmpBak.substr(start, strSize));
}
start = end + 1;
if ((isComplexWord || isCall || hasElse || has_for_in || hasPipe || hasAmp) && isKeyWord) { // REMEMBER TO CHANGE THE SAME CODE ABOVE
start = nextKeyWordStart;
}
if (strLSLOCBak.length() > 0) { //add physical SLOC
if (result->addSLOC(strLSLOCBak, lineNumber, trunc_flag)) { //add a logical SLOC
cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", &result->data_name_count);
temp_lines++;
if (data_continue == true || cnt > 0) {
result->data_lines[LOG]++;
phys_data_lines = temp_lines;
}
else {
result->exec_lines[LOG]++;
phys_exec_lines = temp_lines;
}
}
else if (data_continue == true)
phys_data_lines = temp_lines;
else
phys_exec_lines = temp_lines;
}
data_continue = false;
temp_lines = 0;
strLSLOC = strLSLOCBak = "";
}
delete[] line;
line = NULL;
}
}
/*!
* Parses lines for function/method names.
*
* \param line line to be processed
* \param lastline last line processed
* \param functionStack stack of functions
* \param functionName function name found
*
* \return 1 if function name is found
*/
int CBatchCounter::ParseFunctionName(const string &line, string &lastline,
filemap &functionStack, string &functionName, unsigned int &functionCount)
{
/*
* functionStack is used to record block names encountered, it will be poped when its closing "}" is encountered
* cyclomatic_stack is used to record the previous cyc_count when start of block is encountered, it will be poped
* when end of block is encountered and poped value will be added to the current cyc_cnt
*/
string tline, str;
//size_t i, idx, tidx, cnt;
size_t idx; // warning fix
tline = CUtil::TrimString(line, 0);
// Look for label
idx = tline.find(':');
if(idx == 0) {
// check if there is any function in the stack that has noot been closed
if(!functionStack.empty()) {
// pop start of the block from functionStack
functionName = functionStack.back().line;
functionCount = functionStack.back().lineNumber;
functionStack.pop_back();
// push current function into stack
lineElement element(++functionCount, CUtil::ClearRedundantSpaces(tline));
functionStack.push_back(element);
lastline.erase();
return 1;
}
str = CUtil::ClearRedundantSpaces(tline);
lineElement element(++functionCount, str);
functionStack.push_back(element);
lastline.erase();
}
// Look for end of function
idx = CUtil::FindKeyword(tline, "goto");
if(idx != string::npos) {
str = CUtil::TrimString(tline.substr(idx+4));
idx = CUtil::FindKeyword(str, ":eof");
}
if(idx == 0 && !functionStack.empty()) {
functionName = functionStack.back().line;
functionCount = functionStack.back().lineNumber;
functionStack.pop_back();
lastline.erase();
return 1;
}
// update lastline
lastline = tline;
// code that belong to "main" block
if(functionStack.empty()) {
return 2;
}
return 0;
}
/*!
* Counts file language complexity based on specified language keywords/characters.
*
* \param fmap list of processed file lines
* \param result counter results
*
* \return method status
*/
int CBatchCounter::CountComplexity(filemap* fmap, results* result)
{
if (classtype == UNKNOWN || classtype == DATAFILE)
return 0;
filemap::iterator fit;
size_t idx;
unsigned int cnt, ret, cyclomatic_cnt = 0, ignore_cyclomatic_cnt = 0, main_cyclomatic_cnt = 0, function_count = 0, cyclomatic_logic_cnt = 0, main_cyclomatic_logic_cnt = 1;
string line, lastline, file_ext, function_name = "";
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
filemap function_stack;
stack<unsigned int> cyclomatic_stack;
stack<unsigned int> cyclomatic_logic_stack;
map<unsigned int, lineElement> function_map;
map<unsigned int, lineElement> logical_map;
bool process_cyclomatic_complexity = false;
// check whether to process cyclomatic complexity
if (cmplx_cyclomatic_list.size() > 0)
{
process_cyclomatic_complexity = true;
if (skip_cmplx_cyclomatic_file_extension_list.size() > 0)
{
idx = result->file_name.find_last_of(".");
if (idx != string::npos)
{
file_ext = result->file_name.substr(idx);
file_ext = CUtil::ToLower(file_ext);
if (find(skip_cmplx_cyclomatic_file_extension_list.begin(), skip_cmplx_cyclomatic_file_extension_list.end(), file_ext) != skip_cmplx_cyclomatic_file_extension_list.end())
process_cyclomatic_complexity = false;
}
}
}
// process each line
for (fit = fmap->begin(); fit != fmap->end(); fit++)
{
line = fit->line;
if (CUtil::CheckBlank(line))
continue;
line = " " + line;
// mathematical functions
cnt = 0;
CUtil::CountTally(line, math_func_list, cnt, 1, exclude, "", "", &result->math_func_count, casesensitive);
result->cmplx_math_lines += cnt;
// trigonometric functions
cnt = 0;
CUtil::CountTally(line, trig_func_list, cnt, 1, exclude, "", "", &result->trig_func_count, casesensitive);
result->cmplx_trig_lines += cnt;
// logarithmic functions
cnt = 0;
CUtil::CountTally(line, log_func_list, cnt, 1, exclude, "", "", &result->log_func_count, casesensitive);
result->cmplx_logarithm_lines += cnt;
// calculations
cnt = 0;
CUtil::CountTally(line, cmplx_calc_list, cnt, 1, exclude, "", "", &result->cmplx_calc_count, casesensitive);
result->cmplx_calc_lines += cnt;
// conditionals
cnt = 0;
CUtil::CountTally(line, cmplx_cond_list, cnt, 1, exclude, "", "", &result->cmplx_cond_count, casesensitive);
result->cmplx_cond_lines += cnt;
// logical operators
cnt = 0;
CUtil::CountTally(line, cmplx_logic_list, cnt, 1, exclude, "", "", &result->cmplx_logic_count, casesensitive);
result->cmplx_logic_lines += cnt;
// preprocessor directives
cnt = 0;
CUtil::CountTally(line, cmplx_preproc_list, cnt, 1, exclude, "", "", &result->cmplx_preproc_count, casesensitive);
result->cmplx_preproc_lines += cnt;
// assignments
cnt = 0;
CUtil::CountTally(line, cmplx_assign_list, cnt, 1, exclude, "", "", &result->cmplx_assign_count, casesensitive);
result->cmplx_assign_lines += cnt;
/* No pointers for DOS batch commands
// pointers
cnt = 0;
// Pointers are embedded syntax so there is NO exclude string or include strings
CUtil::CountTally(line, cmplx_pointer_list, cnt, 1, "", "", "", &result->cmplx_pointer_count, casesensitive);
result->cmplx_pointer_lines += cnt;
*/
// cyclomatic complexity
if (process_cyclomatic_complexity)
{
// search for cyclomatic complexity keywords
CUtil::CountTally(line, cmplx_cyclomatic_list, cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive);
// search for keywords to exclude
if (ignore_cmplx_cyclomatic_list.size() > 0)
CUtil::CountTally(line, ignore_cmplx_cyclomatic_list, ignore_cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive);
// search for cyclomatic complexity logical keywords
if (cmplx_cyclomatic_logic_list.size() > 0)
CUtil::CountTally(line, cmplx_cyclomatic_logic_list, cyclomatic_logic_cnt, 1, exclude, "", "", 0, casesensitive);
// parse function name if found
ret = (unsigned int)ParseFunctionName( line, lastline, function_stack, function_name, function_count );
if (ret != 1 && !cyclomatic_stack.empty() && cyclomatic_stack.size() == function_stack.size())
{
// remove count stack entry for non-function names
cyclomatic_cnt += cyclomatic_stack.top();
ignore_cyclomatic_cnt = 0;
cyclomatic_stack.pop();
}
if (ret != 1 && !cyclomatic_logic_stack.empty() && cyclomatic_logic_stack.size() == function_stack.size())
{
// remove count stack entry for non-function names
cyclomatic_logic_cnt += cyclomatic_logic_stack.top();
cyclomatic_logic_stack.pop();
}
if (ret == 1)
{
// capture count at end of function
lineElement element(cyclomatic_cnt - ignore_cyclomatic_cnt + 1, function_name);
function_map[function_count] = element;
lineElement n_element(cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt + 1, function_name);
logical_map[function_count] = n_element;
//there is no embedded functions in DOS_Batch
cyclomatic_cnt = 0;
cyclomatic_logic_cnt = 0;
function_name = "";
ignore_cyclomatic_cnt = 0;
}
else if (ret == 2)
{
if (main_cyclomatic_cnt < 1)
main_cyclomatic_cnt = 1; // add 1 for main function here in case no other decision points are found in main
// some code doesn't belong to any function
main_cyclomatic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt;
main_cyclomatic_logic_cnt += cyclomatic_cnt - ignore_cyclomatic_cnt + cyclomatic_logic_cnt;
cyclomatic_cnt = ignore_cyclomatic_cnt = cyclomatic_logic_cnt = 0;
}
else {
if (!function_stack.empty() && (function_stack.size() > cyclomatic_stack.size() + 1 || (cyclomatic_stack.empty() && function_stack.size() > 1)))
{
// capture previous complexity count from open function
cyclomatic_stack.push(cyclomatic_cnt - ignore_cyclomatic_cnt);
cyclomatic_cnt = ignore_cyclomatic_cnt = 0;
}
if (!function_stack.empty() && (function_stack.size() > cyclomatic_logic_stack.size() + 1 || (cyclomatic_logic_stack.empty() && function_stack.size() > 1)))
{
// capture previous complexity count from open function
cyclomatic_logic_stack.push(cyclomatic_logic_cnt);
cyclomatic_logic_cnt = 0;
}
}
}
}
//process the last function if it exists
if (!function_stack.empty())
{
function_name = function_stack.back().line;
function_count = function_stack.back().lineNumber + 1;
function_stack.pop_back();
lineElement element(cyclomatic_cnt + 1, function_name);
lineElement n_element(cyclomatic_cnt + cyclomatic_logic_cnt + 1, function_name);
function_map[function_count] = element;
logical_map[function_count] = n_element;
}
// done with a file
if (main_cyclomatic_cnt > 0)
{
// add "main" code
lineElement element(main_cyclomatic_cnt, "main");
lineElement n_element(main_cyclomatic_logic_cnt, "main");
function_map[0] = element;
logical_map[0] = n_element;
}
// process ordered functions
for (map<unsigned int, lineElement>::iterator it = function_map.begin(); it != function_map.end(); ++it)
result->cmplx_cycfunct_count.push_back(it->second);
if(cmplx_cyclomatic_logic_list.size() > 0)
{
for (map<unsigned int, lineElement>::iterator it = logical_map.begin(); it != logical_map.end(); ++it)
result->cmplx_cycfunct_CC2_count.push_back(it->second);
}
return 1;
}

50
src/CBatchCounter.h

@ -0,0 +1,50 @@
//! Code counter class definition for the Batch shell script language.
/*!
* \file CBatchCounter.h
*
* This file contains the code counter class definition for the Batch shell script language.
* This also includes the Korn shell language.
*/
#ifndef CBatchCounter_h
#define CBatchCounter_h
#include "CCodeCounter.h"
//! Batch shell script code counter class.
/*!
* \class CBatchCounter
*
* Defines the Batch shell script code counter class.
*/
class CBatchCounter : public CCodeCounter
{
public:
CBatchCounter();
protected:
virtual int PreCountProcess(filemap* fmap);
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak = NULL);
void LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC,
string &strLSLOCBak, bool &data_continue, unsigned int &temp_lines, unsigned int &phys_exec_lines,
unsigned int &phys_data_lines/*, StringVector &loopLevel*/); // warning fix
int ParseFunctionName(const string &line, string &lastline, filemap &functionStack, string &functionName,
unsigned int &functionCount);
int CountComplexity(filemap* fmap, results* result);
StringVector continue_keywords; //!< List of keywords to continue to next line
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CBatchCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CBatchCounter(const CBatchCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CBatchCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CBatchCounter operator=(const CBatchCounter); // Declare without implementation
};
#endif

306
src/CCCounter.cpp

@ -0,0 +1,306 @@
//! Code counter class methods for the C/C++ languages.
/*!
* \file CCCounter.cpp
*
* This file contains the code counter class methods for the C/C++ languages.
*
* Changed UCC 2015.12 release by Randy Maxwell
* Addition of file extensions .inl .inc to support working with Linux and Boost for example
* .cxx .hxx as comments ready for anyone wanting Legacy C++ file support
*/
#include "CCCounter.h"
/*!
* Constructs a CCCounter object.
*/
CCCounter::CCCounter( string lang ) : CCJavaCsScalaCounter( lang )
{
classtype = C_CPP;
language_name = "C_CPP";
//Modification: 11.2016 Ext-4 starts
file_extension = CUtil::getExtensionsToLanguage("C_CPP", file_extension);
/*file_extension.push_back(".c");
file_extension.push_back(".cc");
file_extension.push_back(".cpp");
file_extension.push_back(".cxx"); // Legacy C++ Enable if you want
file_extension.push_back(".inl"); // inline files for example see Boost libraries Modification: 2015.12
// These file types are not processed when doing Cyclomatic Complexity calculations
file_extension.push_back(".h");
file_extension.push_back(".hh");
file_extension.push_back(".hpp");
file_extension.push_back(".hxx"); // Legacy C++ Enable if you want
file_extension.push_back(".inc"); // include files for example see Linux Modification: 2015.12 */
//Modification: 11.2016 Ext-4 ends
directive.push_back("#define");
directive.push_back("#dictionary");
directive.push_back("#error");
directive.push_back("#if");
directive.push_back("#ifdef");
directive.push_back("#ifndef");
directive.push_back("#else");
directive.push_back("#elif");
directive.push_back("#endif");
directive.push_back("#import");
directive.push_back("#include");
directive.push_back("#line");
directive.push_back("#module");
directive.push_back("#pragma");
directive.push_back("#undef");
directive.push_back("#using");
directive.push_back("# define");
directive.push_back("# dictionary");
directive.push_back("# error");
directive.push_back("# if");
directive.push_back("# ifdef");
directive.push_back("# ifndef");
directive.push_back("# else");
directive.push_back("# elif");
directive.push_back("# endif");
directive.push_back("# import");
directive.push_back("# include");
directive.push_back("# line");
directive.push_back("# module");
directive.push_back("# pragma");
directive.push_back("# undef");
directive.push_back("# using");
data_name_list.push_back("asm");
data_name_list.push_back("auto");
data_name_list.push_back("bool");
data_name_list.push_back("char");
data_name_list.push_back("class");
data_name_list.push_back("const");
data_name_list.push_back("double");
data_name_list.push_back("enum");
data_name_list.push_back("explicit");
data_name_list.push_back("extern");
data_name_list.push_back("FILE");
data_name_list.push_back("float");
data_name_list.push_back("friend");
data_name_list.push_back("inline");
data_name_list.push_back("int");
data_name_list.push_back("long");
data_name_list.push_back("mutable");
data_name_list.push_back("namespace");
data_name_list.push_back("operator");
data_name_list.push_back("register");
data_name_list.push_back("short");
data_name_list.push_back("static");
data_name_list.push_back("string");
data_name_list.push_back("struct");
data_name_list.push_back("template");
data_name_list.push_back("typedef");
data_name_list.push_back("union");
data_name_list.push_back("unsigned");
data_name_list.push_back("using");
data_name_list.push_back("virtual");
data_name_list.push_back("void");
data_name_list.push_back("volatile");
data_name_list.push_back("wchar_t");
exec_name_list.push_back("break");
exec_name_list.push_back("case");
exec_name_list.push_back("catch");
exec_name_list.push_back("cerr");
exec_name_list.push_back("cin");
exec_name_list.push_back("clog");
exec_name_list.push_back("const_cast");
exec_name_list.push_back("continue");
exec_name_list.push_back("cout");
exec_name_list.push_back("default");
exec_name_list.push_back("delete");
exec_name_list.push_back("do");
exec_name_list.push_back("dynamic_cast");
exec_name_list.push_back("else");
exec_name_list.push_back("entry");
exec_name_list.push_back("for");
exec_name_list.push_back("goto");
exec_name_list.push_back("if");
exec_name_list.push_back("new");
exec_name_list.push_back("reinterpret_cast");
exec_name_list.push_back("return");
exec_name_list.push_back("sizeof");
exec_name_list.push_back("stderr");
exec_name_list.push_back("stdin");
exec_name_list.push_back("stdout");
exec_name_list.push_back("switch");
exec_name_list.push_back("static_cast");
exec_name_list.push_back("throw");
exec_name_list.push_back("try");
exec_name_list.push_back("typeid");
exec_name_list.push_back("while");
math_func_list.push_back("abs");
math_func_list.push_back("cbrt");
math_func_list.push_back("ceil");
math_func_list.push_back("copysign");
math_func_list.push_back("erf");
math_func_list.push_back("erfc");
math_func_list.push_back("exp");
math_func_list.push_back("exp2");
math_func_list.push_back("expm1");
math_func_list.push_back("fabs");
math_func_list.push_back("fdim");
math_func_list.push_back("floor");
math_func_list.push_back("fma");
math_func_list.push_back("fmax");
math_func_list.push_back("fmin");
math_func_list.push_back("fmod");
math_func_list.push_back("frexp");
math_func_list.push_back("hypot");
math_func_list.push_back("ilogb");
math_func_list.push_back("ldexp");
math_func_list.push_back("lgamma");
math_func_list.push_back("llrint");
math_func_list.push_back("lrint");
math_func_list.push_back("llround");
math_func_list.push_back("lround");
math_func_list.push_back("modf");
math_func_list.push_back("nan");
math_func_list.push_back("nearbyint");
math_func_list.push_back("nextafter");
math_func_list.push_back("nexttoward");
math_func_list.push_back("pow");
math_func_list.push_back("remainder");
math_func_list.push_back("remquo");
math_func_list.push_back("rint");
math_func_list.push_back("round");
math_func_list.push_back("scalbln");
math_func_list.push_back("scalbn");
math_func_list.push_back("sqrt");
math_func_list.push_back("tgamma");
math_func_list.push_back("trunc");
trig_func_list.push_back("cos");
trig_func_list.push_back("cosh");
trig_func_list.push_back("sin");
trig_func_list.push_back("sinh");
trig_func_list.push_back("tan");
trig_func_list.push_back("tanh");
trig_func_list.push_back("acos");
trig_func_list.push_back("acosh");
trig_func_list.push_back("asinh");
trig_func_list.push_back("atanh");
trig_func_list.push_back("asin");
trig_func_list.push_back("atan");
trig_func_list.push_back("atan2");
log_func_list.push_back("log");
log_func_list.push_back("log10");
log_func_list.push_back("log1p");
log_func_list.push_back("log2");
log_func_list.push_back("logb");
cmplx_preproc_list.push_back("#define");
cmplx_preproc_list.push_back("#dictionary");
cmplx_preproc_list.push_back("#elif");
cmplx_preproc_list.push_back("#else");
cmplx_preproc_list.push_back("#endif");
cmplx_preproc_list.push_back("#error");
cmplx_preproc_list.push_back("#if");
cmplx_preproc_list.push_back("#ifdef");
cmplx_preproc_list.push_back("#ifndef");
cmplx_preproc_list.push_back("#import");
cmplx_preproc_list.push_back("#include");
cmplx_preproc_list.push_back("#line");
cmplx_preproc_list.push_back("#module");
cmplx_preproc_list.push_back("#pragma");
cmplx_preproc_list.push_back("#undef");
cmplx_preproc_list.push_back("#using");
cmplx_pointer_list.push_back("->");
/* Below Set in CCJavaCsScalaCounter
cmplx_cyclomatic_list.push_back("if");
cmplx_cyclomatic_list.push_back("case");
cmplx_cyclomatic_list.push_back("while");
cmplx_cyclomatic_list.push_back("for");
cmplx_cyclomatic_list.push_back("catch");
cmplx_cyclomatic_list.push_back("?");
cmplx_cyclomatic_logic_list.push_back("||");
cmplx_cyclomatic_logic_list.push_back("&&");
//cmplx_cyclomatic_logic_list.push_back("^");
cmplx_cyclomatic_case_list.push_back("case");
cmplx_cyclomatic_switch_list.push_back("switch");
*/
skip_cmplx_cyclomatic_file_extension_list.push_back(".h");
skip_cmplx_cyclomatic_file_extension_list.push_back(".hh");
skip_cmplx_cyclomatic_file_extension_list.push_back(".hpp");
//skip_cmplx_cyclomatic_file_extension_list.push_back(".hxx"); // Legacy C++ Enable if you want
skip_cmplx_cyclomatic_file_extension_list.push_back(".inc");
two_char_operator_list.push_back("->");
two_char_operator_list.push_back("::");
for (StringVector::iterator it = cmplx_cyclomatic_list.begin(); it != cmplx_cyclomatic_list.end(); it++)
keyword_operators.insert(*it);
for (StringVector::iterator it = cmplx_preproc_list.begin(); it != cmplx_preproc_list.end(); it++)
keyword_operators.insert(*it);
for (StringVector::iterator it = directive.begin(); it != directive.end(); it++)
keyword_operators.insert(*it);
for (StringVector::iterator it = data_name_list.begin(); it != data_name_list.end(); it++)
keyword_operators.insert(*it);
for (StringVector::iterator it = exec_name_list.begin(); it != exec_name_list.end(); it++)
keyword_operators.insert(*it);
}
/*!
* Returns true if the line ends with '\', which is a way to
* continue a line of code in C++ (and other languages)to the next line.
*
* \param line the string to examine
* \return true if the line ends with '\' else false
*/
bool CCCounter::EndsWithOpenString(const string &line) {
if (line.size() > 0 && line[line.size() - 1] == '\\') {
return true;
}
return false;
}
/*!
* Concatenates all the physical lines belonging to a multiline string and stores
* this in the parameter 'line'. If the source line at curr_line_idx does not contain any multiline string
* then this function will store just that one source line into 'line' and return
* the original curr_line_idx that was passed into the function.
*
* \param curr_line_idx the index of the line in fmap from which to begin
* \param line the concatenation of all source lines beginning from curr_line_idx until there is no multistring
* \param fmap the source code for the file
* \param nonfunction_operator_counts the map for counting the number of times a nonfunction operator (e.g. symbolic operators such as '+' and '[')
*
* \return the index into fmap at which the first physical line, at or after curr_line_idx, does not continue to the next source line as a multiline string
*/
int CCCounter::GetLineUntilEndOfMultistringIfAny(int curr_line_idx, string &line, filemap &fmap, map<string, unsigned int> &nonfunction_operator_counts) {
string line_with_end_of_multistring_if_any = "";
//Modification: 2018.01 USC, changed data type to size_t
size_t current_line_idx = curr_line_idx ;
string curr_line = CUtil::TrimString(fmap[current_line_idx].line, 1);
while (EndsWithOpenString(curr_line) && current_line_idx < fmap.size() - 1) {
line_with_end_of_multistring_if_any.append(curr_line.substr(0, curr_line.size() - 1));
nonfunction_operator_counts["\\"]++;
current_line_idx++;
curr_line = CUtil::TrimString(fmap[current_line_idx].line, 1);
}
line = line_with_end_of_multistring_if_any + curr_line;
return current_line_idx;
}

43
src/CCCounter.h

@ -0,0 +1,43 @@
//! Code counter class definition for the C/C++ languages.
/*!
* \file CCCounter.h
*
* This file contains the code counter class definition for the C/C++ languages.
*/
#ifndef CCCounter_h
#define CCCounter_h
#include "CCJavaCsScalaCounter.h"
//! C/C++ code counter class.
/*!
* \class CCCounter
*
* Defines the C/C++ code counter class.
*/
class CCCounter : public CCJavaCsScalaCounter
{
public:
// Set the language so base class constructors set values as needed
CCCounter( string lang = "C_CPP" );
//Modification: 2018.01 Integration starts
bool EndsWithOpenString(const string &line);
int GetLineUntilEndOfMultistringIfAny(int curr_line_idx, string &line, filemap &fmap, map<string, unsigned int> &nonfunction_operator_counts);
//Modification: 2018.01 Integration ends
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CCCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CCCounter(const CCCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CCCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CCCounter operator=(const CCCounter); // Declare without implementation
};
#endif

661
src/CCFScriptCounter.cpp

@ -0,0 +1,661 @@
//! Code counter class methods for the CFScript language.
/*!
* \file CCFScriptCounter.cpp
*
* This file contains the code counter class methods for the CFScript language.
*/
#include "CCFScriptCounter.h"
/*!
* Constructs a CCFScriptCounter object.
*/
CCFScriptCounter::CCFScriptCounter()
{
classtype = CFSCRIPT;
language_name = "CFScript";
casesensitive = false;
//Modification: 11.2016 Ext-4
file_extension = CUtil::getExtensionsToLanguage("CFScript", file_extension);
//file_extension.push_back(".cfs");
QuoteStart = "\"'";
QuoteEnd = "\"'";
LineCommentStart.push_back("//");
BlockCommentStart.push_back("/*");
BlockCommentEnd.push_back("*/");
data_name_list.push_back("function");
data_name_list.push_back("import");
data_name_list.push_back("include");
data_name_list.push_back("interface");
data_name_list.push_back("property");
data_name_list.push_back("var");
exec_name_list.push_back("abort");
exec_name_list.push_back("break");
exec_name_list.push_back("case");
exec_name_list.push_back("catch");
exec_name_list.push_back("component");
exec_name_list.push_back("continue");
exec_name_list.push_back("createobject");
exec_name_list.push_back("default");
exec_name_list.push_back("else");
exec_name_list.push_back("exit");
exec_name_list.push_back("finally");
exec_name_list.push_back("for");
exec_name_list.push_back("if");
exec_name_list.push_back("location");
exec_name_list.push_back("lock");
exec_name_list.push_back("new");
exec_name_list.push_back("param");
exec_name_list.push_back("pageecoding");
exec_name_list.push_back("rethrow");
exec_name_list.push_back("return");
exec_name_list.push_back("savecontent");
exec_name_list.push_back("switch");
exec_name_list.push_back("thread");
exec_name_list.push_back("throw");
exec_name_list.push_back("trace");
exec_name_list.push_back("transaction");
exec_name_list.push_back("try");
exec_name_list.push_back("while");
exec_name_list.push_back("writedump");
exec_name_list.push_back("writelog");
exec_name_list.push_back("writeoutput");
math_func_list.push_back("abs");
math_func_list.push_back("arrayavg");
math_func_list.push_back("arraysum");
math_func_list.push_back("ceiling");
math_func_list.push_back("decrementvalue");
math_func_list.push_back("exp");
math_func_list.push_back("fix");
math_func_list.push_back("incrementvalue");
math_func_list.push_back("int");
math_func_list.push_back("max");
math_func_list.push_back("min");
math_func_list.push_back("mod");
math_func_list.push_back("pi");
math_func_list.push_back("precisionevaluate");
math_func_list.push_back("rand");
math_func_list.push_back("randomize");
math_func_list.push_back("randrange");
math_func_list.push_back("round");
math_func_list.push_back("sgn");
math_func_list.push_back("sqr");
trig_func_list.push_back("acos");
trig_func_list.push_back("asin");
trig_func_list.push_back("atn");
trig_func_list.push_back("cos");
trig_func_list.push_back("sin");
trig_func_list.push_back("tan");
log_func_list.push_back("log");
log_func_list.push_back("log10");
cmplx_calc_list.push_back("+");
cmplx_calc_list.push_back("-");
cmplx_calc_list.push_back("*");
cmplx_calc_list.push_back("/");
cmplx_calc_list.push_back("**");
cmplx_cond_list.push_back("case");
cmplx_cond_list.push_back("else");
cmplx_cond_list.push_back("for");
cmplx_cond_list.push_back("if");
cmplx_cond_list.push_back("switch");
cmplx_cond_list.push_back("while");
cmplx_cond_list.push_back("?");
cmplx_logic_list.push_back("==");
cmplx_logic_list.push_back("!=");
cmplx_logic_list.push_back(">");
cmplx_logic_list.push_back("<");
cmplx_logic_list.push_back(">=");
cmplx_logic_list.push_back("=<");
cmplx_logic_list.push_back("eq");
cmplx_logic_list.push_back("neq");
cmplx_logic_list.push_back("gt");
cmplx_logic_list.push_back("lt");
cmplx_logic_list.push_back("gte");
cmplx_logic_list.push_back("lte");
cmplx_assign_list.push_back("=");
cmplx_cyclomatic_list.push_back("if");
cmplx_cyclomatic_list.push_back("for");
cmplx_cyclomatic_list.push_back("case");
cmplx_cyclomatic_list.push_back("elif");
cmplx_cyclomatic_list.push_back("while");
//cmplx_cyclomatic_list.push_back("switch");
cmplx_cyclomatic_list.push_back("?");
//there is no bollean operators in CFScript, so no CC2 results.
cmplx_cyclomatic_case_list.push_back("case");
cmplx_cyclomatic_switch_list.push_back("switch");
}
/*!
* Processes physical and logical lines according to language specific rules.
* NOTE: all the blank lines +
* whole line comments +
* lines with compiler directives
* should have been blanked from filemap by previous processing
* before reaching this function
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CCFScriptCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak)
{
unsigned int paren_count = 0;
bool for_flag = false;
bool found_forifwhile = false;
bool found_while = false;
char prev_char = 0;
bool data_continue = false;
bool inArrayDec = false;
string strLSLOC = "";
string strLSLOCBak = "";
unsigned int openBrackets = 0;
filemap::iterator fit, fitbak;
string line, lineBak;
StringVector loopLevel;
unsigned int phys_exec_lines = 0;
unsigned int phys_data_lines = 0;
unsigned int temp_lines = 0;
unsigned int cnt = 0;
// two strings used for string match
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
for (fit = fmap->begin(), fitbak = fmapBak->begin(); fit != fmap->end(); fit++, fitbak++)
{
line = fit->line;
// insert blank at the beginning(for searching keywords
line = ' ' + line;
lineBak = ' ' + fitbak->line;
// do not process blank lines
// blank line means blank_line/comment_line/directive
if (!CUtil::CheckBlank(line))
{
LSLOC(result, line, fit->lineNumber, lineBak, strLSLOC, strLSLOCBak, paren_count, for_flag, found_forifwhile,
found_while, prev_char, data_continue, temp_lines, phys_exec_lines, phys_data_lines, inArrayDec,
openBrackets, loopLevel);
if (print_cmplx)
{
cnt = 0;
CUtil::CountTally(line, exec_name_list, cnt, 1, exclude, "", "", &result->exec_name_count, false);
}
result->exec_lines[PHY] += phys_exec_lines;
phys_exec_lines = 0;
result->data_lines[PHY] += phys_data_lines;
phys_data_lines = 0;
}
}
return 1;
}
/*!
* Extracts and stores logical lines of code.
* Determines and extract logical SLOC to place in the result variable
* using addSLOC function. Each time the addSLOC function is called,
* a new logical SLOC is added. This function assumes that the directive
* is handled before it is called.
*
* \param result counter results
* \param line processed physical line of code
* \param lineBak original physical line of code
* \param strLSLOC processed logical string
* \param strLSLOCBak original logical string
* \param paren_cnt count of parenthesis
* \param forflag found for flag
* \param found_forifwhile found for, if, or while flag
* \param found_while found while flag
* \param prev_char previous character
* \param data_continue continuation of a data declaration line
* \param temp_lines tracks physical line count
* \param phys_exec_lines number of physical executable lines
* \param phys_data_lines number of physical data lines
* \param inArrayDec marks an array declaration
* \param openBrackets number of open brackets (no matching close bracket)
* \param loopLevel nested loop level
*/
void CCFScriptCounter::LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
unsigned int &paren_cnt, bool &forflag, bool &found_forifwhile, bool &found_while,
char &prev_char, bool &data_continue, unsigned int &temp_lines,
unsigned int &phys_exec_lines, unsigned int &phys_data_lines, bool &inArrayDec,
unsigned int &openBrackets, StringVector &loopLevel)
{
// paren_cnt is used with 'for' statement only
size_t start = 0; //starting index of the working string
size_t i = 0, strSize;
bool found_do, found_try, found_else, trunc_flag = false;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$:";
unsigned int cnt = 0;
string tmp = CUtil::TrimString(strLSLOC);
// do, try
found_do = (CUtil::FindKeyword(tmp, "do", 0, TO_END_OF_STRING, false) != string::npos);
found_try = (CUtil::FindKeyword(tmp, "try", 0, TO_END_OF_STRING, false) != string::npos);
// else is treated differently, else is included in SLOC, do and try are not
found_else = (CUtil::FindKeyword(tmp, "else", 0, TO_END_OF_STRING, false) != string::npos);
while (i < line.length()) // there may be more than 1 logical SLOC in this line
{
switch (line[i])
{
case ';': case '{': // LSLOC terminators
// ';' for normal executable or declaration statement
// '{' for starting a function or 'do' statement or a block (which is counted)
// get the previous logical mark until i-1 index is the new LSLOC
// except 'do' precedes '{'
// except '}' precedes ';' ??
if (paren_cnt > 0 && line[i] == ';') // do nothing inside 'for' statement
break;
// record open bracket for nested loop processing
if (print_cmplx)
{
if (line[i] == '{')
{
openBrackets++;
if ((unsigned int)loopLevel.size() < openBrackets)
loopLevel.push_back("");
}
else
{
if ((unsigned int)loopLevel.size() > openBrackets && openBrackets > 0)
loopLevel.pop_back();
}
}
// case 'while(...);', 'while(...) {', and '} while(...);'
// this case is handled in case ')'
if (found_while && found_forifwhile)
{
found_while = false;
found_forifwhile = false;
start = i + 1;
break;
}
if (line[i] == '{')
{
if (prev_char == '=') inArrayDec = true;
if (inArrayDec) break; // continue until seeing ';'
// case for(...); and if (...) {
if (found_forifwhile) // these specials are handled
{
found_forifwhile = false;
start = i + 1;
break;
}
// check if 'do' precedes '{'
if (!found_do && !found_try && !found_else)
{
// find for 'do' in string before tmp string
tmp = CUtil::TrimString(line.substr(start, i - start));
found_do = (tmp == "do"); // found 'do' statement
found_try = (tmp == "try"); // found 'try' statement
// same as else
found_else = (tmp == "else"); // found 'else' statement
}
if (found_do || found_try || found_else)
{
if (found_do && print_cmplx)
{
if (loopLevel.size() > 0) loopLevel.pop_back();
loopLevel.push_back("do");
}
found_do = false;
found_try = false;
if (!found_else)
{
// everything before 'do', 'try' are cleared
strLSLOC = "";
strLSLOCBak = "";
start = i + 1;
}
break; // do not store '{' following 'do'
}
}
if (line[i] == ';' && prev_char == '}') // wrong, e.g., a[]={1,2,3};
{
// check if in array declaration or not
// if no, skip, otherwise, complete the SLOC containing array declaration
if (!inArrayDec)
{
start = i + 1;
break;
}
}
inArrayDec = false;
// check for empty statement (=1 LSLOC)
if (CUtil::TrimString(line.substr(start, i + 1 - start)) == ";" && strLSLOC.length() < 1)
{
strLSLOC = ";";
strLSLOCBak = ";";
}
else
{
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
}
if (result->addSLOC(strLSLOCBak, lineNumber, trunc_flag))
{
cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", &result->data_name_count, false);
temp_lines++;
if (data_continue == true && line[i] == ';')
{
result->data_lines[LOG]++;
phys_data_lines = temp_lines;
}
else
{
if (cnt > 0 && line[i] == ';')
{
result->data_lines[LOG]++;
phys_data_lines = temp_lines;
}
else
{
result->exec_lines[LOG]++;
phys_exec_lines = temp_lines;
}
}
}
else if (data_continue == true && line[i] == ';')
phys_data_lines = temp_lines;
else
phys_exec_lines = temp_lines;
data_continue = false;
temp_lines = 0;
strLSLOC = strLSLOCBak = "";
start = i + 1;
break;
case '(':
if (forflag)
paren_cnt++;
else
{
// handle 'for', 'while', 'if' the same way
tmp = CUtil::TrimString(line.substr(start,i));
if (CUtil::FindKeyword(tmp, "for", 0, TO_END_OF_STRING, false) != string::npos
|| CUtil::FindKeyword(tmp, "while", 0, TO_END_OF_STRING, false)!= string::npos
|| CUtil::FindKeyword(tmp, "if", 0, TO_END_OF_STRING, false) != string::npos)
{
forflag = true;
paren_cnt++;
if (print_cmplx && (unsigned int)loopLevel.size() > openBrackets && openBrackets > 0)
loopLevel.pop_back();
if (CUtil::FindKeyword(tmp, "while", 0, TO_END_OF_STRING, false)!= string::npos)
{
if (print_cmplx)
loopLevel.push_back("while");
found_while = true;
}
else if (print_cmplx && CUtil::FindKeyword(tmp, "for", 0, TO_END_OF_STRING, false) != string::npos)
{
loopLevel.push_back("for");
}
// record nested loop level
if (print_cmplx)
{
if (CUtil::FindKeyword(tmp, "if", 0, TO_END_OF_STRING, false) == string::npos)
{
unsigned int loopCnt = 0;
for (StringVector::iterator lit = loopLevel.begin(); lit < loopLevel.end(); lit++)
{
if ((*lit) != "")
loopCnt++;
}
if ((unsigned int)result->cmplx_nestloop_count.size() < loopCnt)
result->cmplx_nestloop_count.push_back(1);
else
result->cmplx_nestloop_count[loopCnt-1]++;
}
}
}
}
break;
case ')':
if (forflag)
{
if (paren_cnt > 0)
paren_cnt--;
if (paren_cnt == 0)
{
// handle 'for', 'foreach', 'while', 'if'
strSize = CUtil::TruncateLine(i + 1 - start, strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(start, strSize);
strLSLOCBak += lineBak.substr(start, strSize);
}
if (result->addSLOC(strLSLOCBak, lineNumber, trunc_flag))
result->exec_lines[LOG]++;
strLSLOCBak = strLSLOC = "";
phys_exec_lines = temp_lines;
temp_lines = 0;
start = i + 1;
found_forifwhile = true;
forflag = false;
}
}
break;
case '}':
// skip '}' when found ';' and then '}' because '{' is counted already
// also, {} is also skipped, counted
if (prev_char == ';' || prev_char == '{' || prev_char == '}')
if (!inArrayDec) start = i + 1;
// record close bracket for nested loop processing
if (print_cmplx)
{
// record close bracket for nested loop processing
if (openBrackets > 0)
openBrackets--;
if (loopLevel.size() > 0)
loopLevel.pop_back();
}
break;
}
if (line[i] != ' ' && line[i] != '\t')
{
// if ;}}} --> don't count }}} at all
// also, if {}}} --> don't count }}} at all
//if ( !(line[i] == '}' && (prev_char == ';' || prev_char == '{'))) // see case '}' above
prev_char = line[i];
// change to not found if a char appears before
if (line[i] != ')' && found_forifwhile)
found_forifwhile = false;
}
i++;
}
tmp = CUtil::TrimString(line.substr(start, i - start));
strSize = CUtil::TruncateLine(tmp.length(), strLSLOC.length(), this->lsloc_truncate, trunc_flag);
if (strSize > 0)
{
strLSLOC += tmp.substr(0, strSize);
tmp = CUtil::TrimString(lineBak.substr(start, i - start));
strLSLOCBak += tmp.substr(0, strSize);
}
// make sure that we are not beginning to process a new data line
cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", NULL, false);
if (cnt > 0)
data_continue = true;
if (data_continue)
temp_lines++;
if (temp_lines == 0 && phys_data_lines == 0 && phys_exec_lines == 0)
phys_exec_lines = 1;
}
/*!
* Parses lines for function/method names.
*
* \param line line to be processed
* \param lastline last line processed
* \param functionStack stack of functions
* \param functionName function name found
* \param functionCount function count found
*
* \return 1 if function name is found
*/
int CCFScriptCounter::ParseFunctionName(const string &line, string &lastline,
filemap &functionStack, string &functionName, unsigned int &functionCount)
{
string tline, str;
size_t idx, tidx, cnt, cnt2;
unsigned int fcnt;
unsigned int cyclomatic_cnt = 0;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
tline = CUtil::TrimString(line);
idx = tline.find('{');
if (idx != string::npos)
{
// check whether it is at first index, if yes then function name is at above line
if (idx == 0)
{
lineElement element(++functionCount, lastline);
functionStack.push_back(element);
lastline.erase();
}
else
{
str = tline.substr(0, idx);
tidx = cnt = cnt2 = 0;
if (str[0] != '(' && str[0] != ':' && (lastline.length() < 1 || lastline[lastline.length() - 1] != ':'))
{
while (tidx != string::npos)
{
tidx = str.find('(', tidx);
if (tidx != string::npos)
{
cnt++;
tidx++;
}
}
if (cnt > 0)
{
tidx = 0;
while (tidx != string::npos)
{
tidx = str.find(')', tidx);
if (tidx != string::npos)
{
cnt2++;
tidx++;
}
}
}
}
// make sure parentheses are closed and no parent class listed
if ((cnt > 0 && cnt == cnt2) || (lastline.length() > 0 && lastline[lastline.length() - 1] == ';'))
lastline = str;
else
lastline += " " + str;
lineElement element(++functionCount, CUtil::TrimString(lastline));
functionStack.push_back(element);
lastline.erase();
}
}
else if (tline.length() > 0 && tline[tline.length() - 1] != ';' &&
lastline.length() > 0 && lastline[lastline.length() - 1] != ';')
{
// append until all parentheses are closed
tidx = lastline.find('(');
if (tidx != string::npos)
{
cnt = 1;
while (tidx != string::npos)
{
tidx = lastline.find('(', tidx + 1);
if (tidx != string::npos)
cnt++;
}
tidx = lastline.find(')');
while (tidx != string::npos)
{
cnt++;
tidx = lastline.find(')', tidx + 1);
}
if (cnt % 2 != 0)
lastline += " " + tline;
else
lastline = tline;
}
else
lastline = tline;
}
else
lastline = tline;
idx = line.find('}');
if (idx != string::npos && !functionStack.empty())
{
str = functionStack.back().line;
fcnt = functionStack.back().lineNumber;
functionStack.pop_back();
idx = str.find('(');
if (idx != string::npos)
{
// search for cyclomatic complexity keywords and other possible keywords
CUtil::CountTally(str, cmplx_cyclomatic_list, cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive);
if (cyclomatic_cnt <= 0 && CUtil::FindKeyword(str, "switch") == string::npos &&
CUtil::FindKeyword(str, "try") == string::npos && CUtil::FindKeyword(str, "finally") == string::npos &&
CUtil::FindKeyword(str, "return") == string::npos && str.find('=') == string::npos)
{
functionName = CUtil::ClearRedundantSpaces(str.substr(0, idx));
functionCount = fcnt;
lastline.erase();
return 1;
}
}
lastline.erase();
}
return 0;
}

46
src/CCFScriptCounter.h

@ -0,0 +1,46 @@
//! Code counter class definition for the CFScript language.
/*!
* \file CCFScriptCounter.h
*
* This file contains the code counter class definition for the CFScript language.
*/
#ifndef CCFScriptCounter_h
#define CCFScriptCounter_h
#include "CCodeCounter.h"
//! CFScript code counter class.
/*!
* \class CCFScriptCounter
*
* Defines the CFScript code counter class.
*/
class CCFScriptCounter : public CCodeCounter
{
public:
CCFScriptCounter();
protected:
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak = NULL);
void LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
unsigned int &paren_cnt, bool &forflag, bool &found_forifwhile, bool &found_while, char &prev_char,
bool &data_continue, unsigned int &temp_lines, unsigned int &phys_exec_lines, unsigned int &phys_data_lines,
bool &inArrayDec, unsigned int &openBrackets, StringVector &loopLevel);
int ParseFunctionName(const string &line, string &lastline, filemap &functionStack, string &functionName,
unsigned int &functionCount);
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CCFScriptCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CCFScriptCounter(const CCFScriptCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CCFScriptCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CCFScriptCounter operator=(const CCFScriptCounter); // Declare without implementation
};
#endif

1396
src/CCJavaCsScalaCounter.cpp
File diff suppressed because it is too large
View File

67
src/CCJavaCsScalaCounter.h

@ -0,0 +1,67 @@
//! Code counter class definition for the C/C++, Java, and C# languages.
/*!
* \file CCJavaCsCounter.h
*
* This file contains the code counter class definition for the C/C++, Java, and C# languages.
*/
#ifndef CCJavaCsScalaCounter_h
#define CCJavaCsScalaCounter_h
#include "CCodeCounter.h"
//! C/C++, Java, C# and Scala code counter common base class.
/*!
* \class CCJavaCsCounter
*
* Defines the C/C++, Java, C# and Scala code counter class.
*/
class CCJavaCsScalaCounter : public CCodeCounter
{
public:
CCJavaCsScalaCounter( string lang = "LANGUAGE_NOT_SET" );
protected:
virtual int CountDirectiveSLOC(filemap* fmap, results* result, filemap* fmapmBak = NULL);
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapmBak = NULL);
void LSLOC(results* result, string line, size_t lineNumber, string lineBak, string &strLSLOC, string &strLSLOCBak,
unsigned int &paren_cnt, bool &forflag, bool &found_forifwhile, bool &found_while, char &prev_char, bool &data_continue,
unsigned int &temp_lines, unsigned int &phys_exec_lines, unsigned int &phys_data_lines,
bool &inArrayDec, bool &found_for, unsigned int &openBrackets, StringVector &loopLevel);
virtual int ParseFunctionName(const string &line, string &lastline,
filemap &functionStack, string &functionName, unsigned int &functionCount);
//Modification: 2018.01 Integration starts
int FindIdxOfNextQuote(const string &line, int start_pos, const char &quote);
int RemoveStringsAndChars(string &line, map<string, unsigned int> &string_char_counts, const bool &add_to_count);
bool IsEitherFunctionDefinitionOrInvocation(string line, string &function_name);
bool IsFunctionDefinition(int line_idx, filemap &fmap, string &function_name);
void SumUp(map<string, map<string, unsigned int> > &add_from_counts, map<string, unsigned int> &into_counts);
bool IsLastLineOfFunction(map<string, unsigned int> &nonfunction_operator_counts);
int CountOperatorsAndOperands(string &line,
map<string, unsigned int> &string_char_counts,
map<string, unsigned int> &word_counts,
map<string, unsigned int> &bool_counts,
map<string, unsigned int> &number_counts,
map<string, unsigned int> &function_counts,
map<string, unsigned int> &nonfunction_operator_counts);
void RemoveSymbolsExceptOpenRoundBracketOfFunction(string &line, map<string, unsigned int> &nonfunction_operator_counts, const bool &should_count);
bool IsAlphanumericOrUnderscore(const char &c);
virtual int GetLineUntilEndOfMultistringIfAny(int, string &, filemap &, map<string, unsigned int> &) { return -1; } //Modification: 2018.05. Integration
virtual int FindHalsteadsVolume(filemap fmapModBak, results* result);
//Modification: 2018.01 Integration ends
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CCJavaCsScalaCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CCJavaCsScalaCounter(const CCJavaCsScalaCounter& rhs);
// Take care of warning C4626: 'CCJavaCsScalaCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CCJavaCsScalaCounter operator=(const CCJavaCsScalaCounter);
};
#endif

979
src/CCobolCounter.cpp

@ -0,0 +1,979 @@
//! Code counter class methods for the Cobol language.
/*!
* \file CCobolCounter.cpp
*
* This file contains the code counter class methods for the Cobol language.
*
* References:
* Wikipedia COBOL language
*
* COBOL 85 Grammer Downloaded grammer text file COBOL85.grm
* Revision: 09-13-06: by Devin Cook
*
* COBOL grammar Version 0.1.1.pdf
* 1999 by Ralf Lammel
*
* Created: 2011? (not sure when or who, not released?) Contributors: QINGYU ZHOU, Nipun, PEI-CHEN
* Revised: 2015.12 by Randy Maxwell
*/
#include "CCobolCounter.h"
/*!
* Constructs a CCobolCounter object.
*/
CCobolCounter::CCobolCounter()
{
classtype = COBOL;
language_name = "COBOL";
//Modification: 11.2016 Ext-4
file_extension = CUtil::getExtensionsToLanguage("COBOL", file_extension);
/*
file_extension.push_back(".cbl");
file_extension.push_back(".cob");
file_extension.push_back(".cpy");*/
QuoteStart = "\"'";
QuoteEnd = "\"'";
//casesensitive = false;
exclude_keywords.push_back("ELSE");
exclude_keywords.push_back("END-EVALUATE");
exclude_keywords.push_back("END-IF");
exclude_keywords.push_back("END-IF.");
exclude_keywords.push_back("END-PERFORM");
exclude_keywords.push_back("END-SEARCH");
exclude_keywords.push_back("THEN");
// added by Nipun
exclude_keywords.push_back("EXCEPTION");
exclude_keywords.push_back("ON EXCEPTION");
exclude_keywords.push_back("NOT ON EXCEPTION");
exclude_keywords.push_back("END-XML");
// -- FINISHED ADDING
sort( exclude_keywords.begin(), exclude_keywords.end() );
exclude_start_keywords.push_back("END");
exclude_start_keywords.push_back("STOP");
//In COBOL, there are only Line Comments
// and they start with either * or /
//An asterisk (*) comment line is printed in the output listing, immediately following the last preceding line.
//A slash (/) comment line is printed on the first line of the next page, and the current page of the output listing is ejected.
// There are no Block comments in COBOL
LineCommentStart.push_back("*");
LineCommentStart.push_back("/");
LineCommentStart.push_back("'");
// === ADDED BY QINGYU ZHOU ===
directive.push_back("BASIS");
directive.push_back("DELETE");
directive.push_back("REPLACE");
directive.push_back("RESET");
directive.push_back("CBL");
directive.push_back("EJECT");
directive.push_back("SERVICE");
directive.push_back("LABEL");
directive.push_back("PROCESS");
directive.push_back("ENTER");
directive.push_back("TITLE");
directive.push_back("RELOAD");
directive.push_back("CONTROL");
directive.push_back("INSERT");
directive.push_back("DEBUGGING");
directive.push_back("COPY");
directive.push_back("TRACE");
directive.push_back("READY");
directive.push_back("PROCEDURE");
// === FINISHED ADDING ===
// Added by Nipun
directive.push_back("*CONTROL");
directive.push_back("*CBL");
directive.push_back("*CONTROL");
directive.push_back("SKIP1");
directive.push_back("SKIP2");
directive.push_back("SKIP3");
directive.push_back("SERVICE RELOAD");
directive.push_back("RESET TRACE");
// FINISHED ADDING
directive.push_back("USE");
directive.push_back("USING");
// Sort for better presentation of results
sort( directive.begin(), directive.end() );
data_name_list.push_back("PIC");
data_name_list.push_back("PICTURE");
exec_name_list.push_back("ACCEPT"); // 2015.12
exec_name_list.push_back("ACCESS");
exec_name_list.push_back("ADVANCING");
exec_name_list.push_back("AFTER");
exec_name_list.push_back("ALL");
exec_name_list.push_back("ARE"); // 2015.12
exec_name_list.push_back("ALPHABETIC"); // 2015.12
exec_name_list.push_back("ALPHANUMERIC"); // 2015.12
exec_name_list.push_back("ALPHANUMERIC-EDITED"); // 2015.12
exec_name_list.push_back("ALTER");
exec_name_list.push_back("ALTERNATIVE"); // 2015.12
exec_name_list.push_back("ASCENDING"); // 2015.12
exec_name_list.push_back("ASSIGN");
exec_name_list.push_back("AT");
exec_name_list.push_back("AUTHOR");
exec_name_list.push_back("BACKGROUND-COLOR"); // 2015.12
exec_name_list.push_back("BEGIN");
exec_name_list.push_back("BEFORE");
exec_name_list.push_back("BINARY"); // 2015.12
exec_name_list.push_back("BLANK"); // 2015.12
exec_name_list.push_back("BLINK"); // 2015.12
exec_name_list.push_back("BLOCK");
exec_name_list.push_back("BOTTOM"); // 2015.12
exec_name_list.push_back("BY");
exec_name_list.push_back("CALL");
exec_name_list.push_back("CANCEL");
exec_name_list.push_back("CD"); // 2015.12
exec_name_list.push_back("CF"); // 2015.12
exec_name_list.push_back("CH"); // 2015.12
exec_name_list.push_back("CHARACTER"); // 2015.12
exec_name_list.push_back("CHARACTERS"); // 2015.12
exec_name_list.push_back("CLASS");
exec_name_list.push_back("CLASS-ID");
exec_name_list.push_back("CLOCK-UNITS"); // 2015.12
exec_name_list.push_back("CLOSE");
exec_name_list.push_back("CODE-SET");
exec_name_list.push_back("COLLATING");
exec_name_list.push_back("COLUMN"); // 2015.12
exec_name_list.push_back("COMMON");
exec_name_list.push_back("COMP");
exec_name_list.push_back("COMPUTATIONAL"); // 2015.12
// ADD BY PEI-CHEN
exec_name_list.push_back("COMPUTE");
// FINISH ADDING
exec_name_list.push_back("CONFIGURATION");
exec_name_list.push_back("CONSOLE"); // 2015.12
exec_name_list.push_back("CONTAINS"); // 2015.12
exec_name_list.push_back("CONTENT");
exec_name_list.push_back("CONTINUE"); // 2015.12
exec_name_list.push_back("CONTROL"); // 2015.12
exec_name_list.push_back("CONTROLS"); // 2015.12
exec_name_list.push_back("CORR"); // 2015.12
exec_name_list.push_back("CORRESPONDING"); // 2015.12
exec_name_list.push_back("COUNT"); // 2015.12
exec_name_list.push_back("CURRENCY");
exec_name_list.push_back("DATA");
exec_name_list.push_back("DATE-COMPILED");
exec_name_list.push_back("DATE-WRITTEN");
exec_name_list.push_back("DAY");
exec_name_list.push_back("DAY-OF-WEEK"); // 2015.12
exec_name_list.push_back("DE"); // 2015.12
exec_name_list.push_back("DEBUGGING");
exec_name_list.push_back("DECIMAL-POINT");
exec_name_list.push_back("DECLARATIVES");
exec_name_list.push_back("DELETE");
exec_name_list.push_back("DELIMITED"); // 2015.12
exec_name_list.push_back("DELIMITER");
exec_name_list.push_back("DEPENDING"); // 2015.12
exec_name_list.push_back("DESCENDING"); // 2015.12
exec_name_list.push_back("DISABLE"); // 2015.12
exec_name_list.push_back("DISPLAY");
exec_name_list.push_back("DIVISION");
exec_name_list.push_back("DUPLICATES"); // 2015.12
exec_name_list.push_back("ENABLE"); // 2015.12
exec_name_list.push_back("END");
exec_name_list.push_back("END-ADD"); // 2015.12
exec_name_list.push_back("END-CALL"); // 2015.12
exec_name_list.push_back("END-COMPUTE"); // 2015.12
exec_name_list.push_back("END-DELETE"); // 2015.12
exec_name_list.push_back("END-DIVIDE"); // 2015.12
exec_name_list.push_back("END-EVALUATE"); // 2015.12
exec_name_list.push_back("END-MULTIPLY"); // 2015.12
exec_name_list.push_back("END-OF-FILE");
exec_name_list.push_back("END-OF-PAGE"); // 2015.12
exec_name_list.push_back("END-REWRITE"); // 2015.12
exec_name_list.push_back("END-STRING"); // 2015.12
exec_name_list.push_back("END-SUBTRACT"); // 2015.12
exec_name_list.push_back("END-UNSTRING"); // 2015.12
exec_name_list.push_back("ENVIRONMENT");
exec_name_list.push_back("EOP"); // 2015.12
exec_name_list.push_back("ERROR");
exec_name_list.push_back("EVALUATE"); // 2015.12
exec_name_list.push_back("EVERY"); // 2015.12
exec_name_list.push_back("EXCEPTION"); // 2015.12
exec_name_list.push_back("EXIT");
exec_name_list.push_back("EXTEND"); // 2015.12
exec_name_list.push_back("EXTERNAL"); // 2015.12
exec_name_list.push_back("FACTORY");
exec_name_list.push_back("FD"); // 2015.12
exec_name_list.push_back("FILE");
exec_name_list.push_back("FILE-CONTROL");
exec_name_list.push_back("FILLER");
exec_name_list.push_back("FINAL"); // 2015.12
exec_name_list.push_back("FOOTING");
exec_name_list.push_back("FOR"); // 2015.12
exec_name_list.push_back("FOREGROUND-COLOR"); // 2015.12
exec_name_list.push_back("FROM");
exec_name_list.push_back("FUNCTION");
exec_name_list.push_back("GENERATE");
exec_name_list.push_back("GIVING"); // 2015.12
exec_name_list.push_back("GLOBAL"); // 2015.12
exec_name_list.push_back("GO");
exec_name_list.push_back("GOTO");
exec_name_list.push_back("GROUP"); // 2015.12
exec_name_list.push_back("HEADING"); // 2015.12
exec_name_list.push_back("HIGH-VALUE"); // 2015.12
exec_name_list.push_back("HIGH-VALUES");
exec_name_list.push_back("HIGHLIGHT"); // 2015.12
exec_name_list.push_back("ID");
exec_name_list.push_back("IDENTIFICATION");
exec_name_list.push_back("IF");
exec_name_list.push_back("IN"); // 2015.12
exec_name_list.push_back("INDEXED");
exec_name_list.push_back("INDICATE"); // 2015.12
exec_name_list.push_back("INHERITS");
exec_name_list.push_back("INITIAL");
exec_name_list.push_back("INITIATE");
exec_name_list.push_back("INPUT"); // 2015.12
exec_name_list.push_back("INPUT-OUTPUT");
exec_name_list.push_back("INSPECT"); // 2015.12
exec_name_list.push_back("INSTALLATION");
exec_name_list.push_back("INTERNAL"); // 2015.12
exec_name_list.push_back("INVALID");
exec_name_list.push_back("INVOKE");
exec_name_list.push_back("IS");
exec_name_list.push_back("I-O"); // 2015.12
exec_name_list.push_back("I-O-CONTROL");
exec_name_list.push_back("JUST"); // 2015.12
exec_name_list.push_back("JUSTIFIED"); // 2015.12
exec_name_list.push_back("KEY");
exec_name_list.push_back("LABEL");
exec_name_list.push_back("LABEL-OF");
exec_name_list.push_back("LEADING"); // 2015.12
exec_name_list.push_back("LEFT"); // 2015.12
exec_name_list.push_back("LIMIT"); // 2015.12
exec_name_list.push_back("LIMITS"); // 2015.12
exec_name_list.push_back("LINAGE"); // 2015.12
exec_name_list.push_back("LINE");
exec_name_list.push_back("LINES");
exec_name_list.push_back("LINKAGE");
exec_name_list.push_back("LOCAL-STORAGE");
exec_name_list.push_back("LOCK"); // 2015.12
exec_name_list.push_back("LOW-VALUE"); // 2015.12
exec_name_list.push_back("LOW-VALUES"); // 2015.12
exec_name_list.push_back("MERGE");
exec_name_list.push_back("MESSAGE"); // 2015.12
exec_name_list.push_back("METHOD-ID");
exec_name_list.push_back("MODE");
exec_name_list.push_back("MOVE");
exec_name_list.push_back("MULTIPLE"); // 2015.12
exec_name_list.push_back("NATIVE"); // 2015.12
exec_name_list.push_back("NEXT"); // 2015.12
exec_name_list.push_back("NOT-END-OF-FILE");
exec_name_list.push_back("NULL"); // 2015.12
exec_name_list.push_back("NULLS"); // 2015.12
exec_name_list.push_back("NUMBER"); // 2015.12
exec_name_list.push_back("NUMERIC"); // 2015.12
exec_name_list.push_back("NUMERIC-EDITED"); // 2015.12
exec_name_list.push_back("OBJECT");
exec_name_list.push_back("OBJECT-COMPUTER");
exec_name_list.push_back("OCCURS");
exec_name_list.push_back("OF"); // 2015.12
exec_name_list.push_back("OFF"); // 2015.12
exec_name_list.push_back("OMITTED"); // 2015.12
exec_name_list.push_back("ON"); // 2015.12
exec_name_list.push_back("OPEN");
exec_name_list.push_back("ORDER"); // 2015.12
exec_name_list.push_back("OUTPUT"); // 2015.12
exec_name_list.push_back("ORGANIZATION");
exec_name_list.push_back("OVERFLOW"); // 2015.12
exec_name_list.push_back("PACKED-DECIMAL"); // 2015.12
exec_name_list.push_back("PADDING");
exec_name_list.push_back("PAGE"); // 2015.12
exec_name_list.push_back("PASSWORD");
exec_name_list.push_back("PERFORM");
exec_name_list.push_back("PF"); // 2015.12
exec_name_list.push_back("PH"); // 2015.12
exec_name_list.push_back("POINTER"); // 2015.12 <<<< Pointer like C++ ? ? ?
exec_name_list.push_back("POSITION"); // 2015.12
exec_name_list.push_back("PRINTING"); // 2015.12
exec_name_list.push_back("PROCEDURE");
exec_name_list.push_back("PROCEDURES"); // 2015.12
exec_name_list.push_back("PROGRAM");
exec_name_list.push_back("PROGRAM-ID");
exec_name_list.push_back("QUOTE"); // 2015.12
exec_name_list.push_back("QUOTES"); // 2015.12
exec_name_list.push_back("READ");
exec_name_list.push_back("RECORD");
exec_name_list.push_back("RECORDS"); // 2015.12
exec_name_list.push_back("RECORDING");
exec_name_list.push_back("RECURSIVE");
exec_name_list.push_back("REDEFINES"); // 2015.12
exec_name_list.push_back("REFERENCE");
exec_name_list.push_back("REFERENCES"); // 2015.12
exec_name_list.push_back("RELATIVE");
exec_name_list.push_back("RELEASE");
exec_name_list.push_back("REMOVAL"); // 2015.12
exec_name_list.push_back("RENAMES"); // 2015.12
exec_name_list.push_back("REPORT"); // 2015.12
exec_name_list.push_back("REPORTING");
exec_name_list.push_back("RERUN"); // 2015.12
exec_name_list.push_back("RESERVE");
exec_name_list.push_back("RESET"); // 2015.12
exec_name_list.push_back("RETURN");
exec_name_list.push_back("REVERSE-VIDEO"); // 2015.12
exec_name_list.push_back("REWIND"); // 2015.12
exec_name_list.push_back("REWRITE");
exec_name_list.push_back("RF"); // 2015.12
exec_name_list.push_back("RH"); // 2015.12
exec_name_list.push_back("RIGHT"); // 2015.12
exec_name_list.push_back("ROUNDED"); // 2015.12
exec_name_list.push_back("SCREEN"); // 2015.12
exec_name_list.push_back("SD"); // 2015.12
// ADD BY PEI-CHEN
exec_name_list.push_back("SEARCH");
// FINISH ADDING
exec_name_list.push_back("SECTION");
exec_name_list.push_back("SECURITY");
exec_name_list.push_back("SEGMENT-LIMIT");
exec_name_list.push_back("SELECT");
exec_name_list.push_back("SEPARATE"); // 2015.12
exec_name_list.push_back("SEQUENCE");
exec_name_list.push_back("SEQUENTIAL");
exec_name_list.push_back("SIGN"); // 2015.12
exec_name_list.push_back("SIZE"); // 2015.12
exec_name_list.push_back("SORT");
exec_name_list.push_back("SORT-MERGE"); // 2015.12
exec_name_list.push_back("SOURCE-COMPUTER");
exec_name_list.push_back("SPACE"); // 2015.12
exec_name_list.push_back("SPACES");
exec_name_list.push_back("SPECIAL-NAMES"); // 2015.12
exec_name_list.push_back("STANDARD"); // 2015.12
exec_name_list.push_back("STANDARD-1"); // 2015.12
exec_name_list.push_back("STANDARD-2"); // 2015.12
exec_name_list.push_back("START");
exec_name_list.push_back("STATUS");
exec_name_list.push_back("STRING"); // 2015.12
exec_name_list.push_back("STOP"); // 2015.12
exec_name_list.push_back("SUPPRESS"); // 2015.12
exec_name_list.push_back("SUM"); // 2015.12
exec_name_list.push_back("SYMBOLIC"); // 2015.12
exec_name_list.push_back("SYNC"); // 2015.12
exec_name_list.push_back("SYNCHRONIZED"); // 2015.12
exec_name_list.push_back("TABLE"); // 2015.12
exec_name_list.push_back("TABLES"); // 2015.12
exec_name_list.push_back("TAPE"); // 2015.12
exec_name_list.push_back("TERMINATE");
exec_name_list.push_back("THAN"); // 2015.12
exec_name_list.push_back("THEN"); // 2015.12
exec_name_list.push_back("THROUGH"); // 2015.12
exec_name_list.push_back("THRU");
exec_name_list.push_back("TIME");
exec_name_list.push_back("TIMES");
exec_name_list.push_back("TO");
exec_name_list.push_back("TOP"); // 2015.12
exec_name_list.push_back("TRAILING"); // 2015.12
exec_name_list.push_back("TRUE"); // 2015.12
exec_name_list.push_back("UNDERLINE"); // 2015.12
exec_name_list.push_back("UNSTRING"); // 2015.12
exec_name_list.push_back("UNTIL");
exec_name_list.push_back("UPON"); // 2015.12
exec_name_list.push_back("USE");
exec_name_list.push_back("USING"); // 2015.12
exec_name_list.push_back("VALUE");
exec_name_list.push_back("VALUES"); // 2015.12
exec_name_list.push_back("VARYING");
exec_name_list.push_back("WHEN");
exec_name_list.push_back("WITH");
exec_name_list.push_back("WORKING-STORAGE");
exec_name_list.push_back("WRITE");
// ADD BY PEI-CHEN
exec_name_list.push_back("XML-CODE");
exec_name_list.push_back("XML-EVENT");
exec_name_list.push_back("XML PARSE");
exec_name_list.push_back("XML-TEXT");
// FINISH ADDING
exec_name_list.push_back("ZERO");
exec_name_list.push_back("ZEROS");
exec_name_list.push_back("ZEROES");
sort( exec_name_list.begin(), exec_name_list.end() );
math_func_list.push_back("-");
math_func_list.push_back("*");
math_func_list.push_back("**");
math_func_list.push_back("/");
math_func_list.push_back("+");
math_func_list.push_back("ADD");
math_func_list.push_back("COMPUTE");
math_func_list.push_back("DIVIDE");
math_func_list.push_back("MULTIPLY");
math_func_list.push_back("SUBTRACT");
math_func_list.push_back("REMAINDER");
cmplx_logic_list.push_back("<");
cmplx_logic_list.push_back("<=");
cmplx_logic_list.push_back("=");
cmplx_logic_list.push_back(">");
cmplx_logic_list.push_back(">=");
cmplx_logic_list.push_back("EQUAL");
cmplx_logic_list.push_back("GREATER");
cmplx_logic_list.push_back("LESS");
cmplx_logic_list.push_back("NOT");
cmplx_logic_list.push_back("NOT=");
cmplx_logic_list.push_back("OR");
// added by Nipun
cmplx_logic_list.push_back("XML GENERATE");
cmplx_logic_list.push_back("XML PARSE");
//---finished adding
cmplx_cond_list.push_back("ELSE IF");
cmplx_cond_list.push_back("EVALUATE");
cmplx_cond_list.push_back("IF");
cmplx_cond_list.push_back("PERFORM");
cmplx_cond_list.push_back("SEARCH");
cmplx_cond_list.push_back("STOP");
cmplx_cond_list.push_back("THEN");
cmplx_cond_list.push_back("WHEN");
cmplx_assign_list.push_back("ACCEPT");
cmplx_assign_list.push_back("COMPUTE");
cmplx_assign_list.push_back("GENERATE");
cmplx_assign_list.push_back("INITIALIZE");
cmplx_assign_list.push_back("INSPECT");
cmplx_assign_list.push_back("MOVE");
cmplx_assign_list.push_back("PARSE");
cmplx_assign_list.push_back("SET");
cmplx_assign_list.push_back("STRING");
cmplx_assign_list.push_back("UNSTRING");
cmplx_assign_list.push_back("XML");
cmplx_cyclomatic_list.push_back("ELSE IF");
cmplx_cyclomatic_list.push_back("END-EVALUATE");
cmplx_cyclomatic_list.push_back("END-IF");
cmplx_cyclomatic_list.push_back("END-PERFORM");
cmplx_cyclomatic_list.push_back("END-SEARCH");
cmplx_cyclomatic_list.push_back("EVALUATE");
cmplx_cyclomatic_list.push_back("IF");
cmplx_cyclomatic_list.push_back("PERFORM");
cmplx_cyclomatic_list.push_back("SEARCH");
cmplx_cyclomatic_list.push_back("STOP RUN");
cmplx_cyclomatic_list.push_back("STOP");
// These used to be in ProcessComplexityMeasures in the old 2011 (never released) COBOL parser
//
// subtract "End If" since "If" captured within "End If" and we also have in-line "If"
// subtract "Case Else" because it is captured by "Case" and should not be counted
ignore_cmplx_cyclomatic_list.push_back("END-EVALUATE");
ignore_cmplx_cyclomatic_list.push_back("END-PERFORM");
ignore_cmplx_cyclomatic_list.push_back("END-SEARCH");
ignore_cmplx_cyclomatic_list.push_back("END-IF");
ignore_cmplx_cyclomatic_list.push_back("STOP RUN");
// EVALUATE is like switch
}
/*!
* Counts directive lines of code.
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CCobolCounter::CountDirectiveSLOC(filemap* fmap, results* result, filemap* /* fmapBak */)
{
bool contd = false, trunc_flag = false;
size_t idx, strSize;
if (classtype == DATAFILE) return 0;
unsigned int cnt = 0;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
string strDirLine = "";
for (filemap::iterator iter = fmap->begin(); iter!=fmap->end(); iter++)
{
if ( CUtil::CheckBlank( iter->line ) )
continue;
// === ADDED BY QINGYU ZHOU ===
TrimSourceLine( iter->line );
// === FINISHED ADDING ===
if ( print_cmplx )
{
cnt = 0;
CUtil::CountTally(" " + iter->line, directive, cnt, 1, exclude, "", "", &result->directive_count);
}
if (!contd)
{
// if not a continuation of a previous directive
for(vector<string>::iterator viter = directive.begin(); viter != directive.end(); viter++)
{
if ((idx = iter->line.find((*viter), 0)) != string::npos && idx == 0)
{
contd = true;
break;
}
}
if (contd)
{
result->directive_lines[PHY]++;
strSize = CUtil::TruncateLine(iter->line.length(), 0, result->trunc_lines, trunc_flag);
if (strSize > 0)
strDirLine = iter->line.substr(0, strSize);
}
}
else
{
// continuation of a previous directive
strSize = CUtil::TruncateLine(iter->line.length(), strDirLine.length(), result->trunc_lines, trunc_flag);
if (strSize > 0)
strDirLine += "\n" + iter->line.substr(0, strSize);
result->directive_lines[PHY]++;
}
if (contd)
{
// if a directive or continuation of a directive (no continuation symbol found)
if (iter->line[iter->line.length()-1] != '_')
{
contd = false;
result->directive_lines[LOG]++;
result->addSLOC(strDirLine, trunc_flag);
}
iter->line = "";
}
}
return 1;
}
/*!
* Processes physical and logical lines according to language specific rules.
* NOTE: all the blank lines +
* whole line comments +
* lines with compiler directives
* should have been blanked from filemap by previous processing
* before reaching this function
*
* \param fmap list of processed file lines
* \param result counter results
* \param fmapBak list of original file lines (same as fmap except it contains unmodified quoted strings)
*
* \return method status
*/
int CCobolCounter::LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak)
{
int retVal = 1;
string strLSLOC = "";
string strLSLOCBak = "";
filemap::iterator fit, fitbak;
string line, lineBak;
size_t prev_pos, strSize, tmpLoc;
unsigned int cnt = 0;
StringVector loopEnd;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
string special = "[]()+/*<>=,@&~!^?:%{}";
string tmpstr;
bool isDataLine = false;
// bool line_continued = false;
bool line_skipped;
bool trunc_flag = false;
bool new_loop = false;
SAVE_TO_2( "Start CCobolCounter::CountComplexity" );
currentPhyLine = 0;
for (fit = fmap->begin(), fitbak = fmapBak->begin(); fit != fmap->end(); fit++, fitbak++)
{
currentPhyLine++;
line = fit->line;
if (CUtil::CheckBlank(line))
continue;
lineBak = fitbak->line;
prev_pos = 0;
// check for inline If..Then
tmpstr = CUtil::TrimString(line);
tmpLoc = CUtil::FindKeyword(tmpstr, "THEN");
if (tmpLoc != string::npos)
{
if (tmpLoc < tmpstr.length() - 4)
tmpLoc += 3;
else
tmpLoc = string::npos;
}
// record nested loops
if ( print_cmplx )
{
new_loop = false;
if (CUtil::FindKeyword(tmpstr, "PERFORM") == 0)
{
loopEnd.push_back("END-PERFORM");
new_loop = true;
}
else if (loopEnd.size() > 0)
{
if (CUtil::FindKeyword(tmpstr, loopEnd.back()) == 0)
loopEnd.pop_back();
}
if (new_loop)
{
if ( result->cmplx_nestloop_count.size() < loopEnd.size() )
result->cmplx_nestloop_count.push_back(1);
else
result->cmplx_nestloop_count[loopEnd.size()-1]++;
}
}
for (size_t i = 0; i < line.size(); i++)
{
if ((line[i] == ':') || (i == line.size() - 1) || tmpLoc != string::npos)
{
if (tmpLoc != string::npos)
{
i = tmpLoc;
tmpLoc = string::npos;
}
else
tmpstr = CUtil::TrimString(line.substr(prev_pos, i - prev_pos + 1));
// exclude SLOC defined in the exclude_keywords
line_skipped = false;
for (vector<string>::iterator stri = exclude_keywords.begin(); stri != exclude_keywords.end(); stri++)
{
if (tmpstr.compare(*stri) == 0)
{
line_skipped = true;
break;
}
}
if (line_skipped)
continue;
// exclude SLOC starting with Next, End
for (StringVector::iterator stri = exclude_start_keywords.begin(); stri != exclude_start_keywords.end(); stri++)
{
if (CUtil::FindKeyword(tmpstr, *stri) == 0)
{
line_skipped = true;
break;
}
}
if (line_skipped)
continue;
strSize = CUtil::TruncateLine(i + 1 - prev_pos, strLSLOC.length(), result->trunc_lines, trunc_flag);
if (strSize > 0)
{
strLSLOC += line.substr(prev_pos, strSize);
strLSLOCBak += lineBak.substr(prev_pos, strSize);
}
cnt = 0;
CUtil::CountTally(strLSLOC, data_name_list, cnt, 1, exclude, "", "", &result->data_name_count);
if (cnt > 0)
{
isDataLine = true;
result->data_lines[LOG]++;
}
else
{
if ( print_cmplx )
{
cnt = 0;
CUtil::CountTally(strLSLOC, exec_name_list, cnt, 1, exclude, "", "", &result->exec_name_count);
}
isDataLine = false;
result->exec_lines[LOG]++;
}
result->addSLOC( strLSLOCBak, trunc_flag ); // add one logical SLOC to the list
strLSLOCBak = "";
strLSLOC = "";
prev_pos = i + 1;
if (tmpLoc != string::npos)
{
tmpLoc = string::npos;
prev_pos++;
}
}
if (special.find_first_of(line[i]) != string::npos)
line[i] = ' ';
}
if (isDataLine)
result->data_lines[PHY]++;
else
result->exec_lines[PHY]++;
}
/* Not needed? Done as ignore_cmplx_cyclomatic_list
if ( print_cmplx )
retVal = ProcessComplexityMeasures( fmap, result );
*/
return retVal;
}
/*!
* Processes file language complexity measures.
*
* \param fmap list of processed file lines
* \param result counter results
*
* \return method status
*/
/* COMMENTED OUT. Now the keywords are in ignore_cmplx_cyclomatic_list
int CCobolCounter::ProcessComplexityMeasures( filemap* fmap, results* result )
{
// process Cyclomatic Complexity (CC) from above COBOL has Cyclomatic Complexity keywords with no skip
SAVE_TO_3( "Start CCobolCounter::ProcessComplexityMeasures" );
result->cyclomatic_complexity = 1;
StringVector::iterator icyc = cmplx_cyclomatic_list.begin();
for (vector<int>::iterator icycc = result->cmplx_cyclomatic_count.begin(); icycc != result->cmplx_cyclomatic_count.end(); icycc++, icyc++)
{
if ((*icyc) == "END-EVALUATE" || (*icyc) == "END-PERFORM" || (*icyc) == "END-SEARCH" || (*icyc) == "END-IF" || (*icyc) == "STOP RUN")
{
// subtract "End If" since "If" captured within "End If" and we also have in-line "If"
// subtract "Case Else" because it is captured by "Case" and should not be counted
result->cyclomatic_complexity -= (*icycc);
}
else
result->cyclomatic_complexity += (*icycc);
}
if ( result->cyclomatic_complexity < 0 )
result->cyclomatic_complexity = 0;
return 1;
} */
int CCobolCounter::TrimSourceLine(string& line)
{
for (unsigned int i = 0; i < line.length() - 1; i++)
{
if (line.at(i) == ' ')
{
int countOfSpaces;
for ( countOfSpaces = 1; i + countOfSpaces < line.length(); countOfSpaces++ )
{
if (line.at(i + countOfSpaces) != ' ')
break;
}
line.erase( i, (unsigned)countOfSpaces - 1 );
}
}
TrimSequenceNumber( line );
if ( TrimIndicator( line ) == 1 )
TrimAreaA( line );
return 1;
}
int CCobolCounter::TrimSequenceNumber( string& line )
{
if ( line.length() < 6)
return 0;
for (int i = 0; i < 6; i++)
{
if ( isdigit( line.at( (unsigned)i ) ) == false )
return 0;
}
line.erase( 0, 6 );
return 1;
}
int CCobolCounter::TrimIndicator( string& line )
{
if ( line.length() > 0 && line.at( 0 ) == ' ' )
{
line.erase( 0, 1 );
return 1;
}
return 0;
}
int CCobolCounter::TrimAreaA( string& line )
{
if ( line.length() < 3 )
return 0;
if ( line.at(2) == ' ' && isalnum( line.at( 0 ) ) && isalnum( line.at( 1 ) ) )
line.erase( 0, 3 );
return 1;
}
/*!
* Counts file language complexity based on specified language keywords/characters.
*
* \param fmap list of processed file lines
* \param result counter results
*
* \return method status
*/
int CCobolCounter::CountComplexity( filemap* fmap, results* result )
{
filemap::iterator fit;
unsigned int cnt, cyclomatic_cnt = 0, cyclomatic_logic_cnt = 0, ignore_cyclomatic_cnt = 0;
//int tmpc;
string line;
string exclude = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
bool line_skipped = false;
// bool process_cyclomatic_complexity = true; // from above COBOL has Complexity keywords and no skip
ENTER_1( "Start" ); // Due to Polymorphism change level above
// try
// {
SAVE_TO_2( "Start CCobolCounter::CountComplexity" );
currentPhyLine = 0;
for ( fit = fmap->begin(); fit != fmap->end(); fit++ )
{
currentPhyLine++;
line = fit->line;
SAVE_TO_2( "CUtil::CheckBlank" );
if ( CUtil::CheckBlank( line ) )
continue;
// exclude keywords in exclude_keywords
line_skipped = false;
for (StringVector::iterator stri = exclude_keywords.begin(); stri != exclude_keywords.end(); stri++)
{
if (CUtil::FindKeyword(line, *stri) == 0)
{
line_skipped = true;
break;
}
}
if ( line_skipped )
continue;
line = " " + line;
// mathematical functions
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Math" );
CUtil::CountTally(line, math_func_list, cnt, 1, exclude, "", "", &result->math_func_count, casesensitive);
result->cmplx_math_lines += cnt;
// trigonometric functions
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Trigonometric" );
CUtil::CountTally(line, trig_func_list, cnt, 1, exclude, "", "", &result->trig_func_count, casesensitive);
result->cmplx_trig_lines += cnt;
// logarithmic functions
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Logarithmic" );
CUtil::CountTally(line, log_func_list, cnt, 1, exclude, "", "", &result->log_func_count, casesensitive);
result->cmplx_logarithm_lines += cnt;
// calculations
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Calculations" );
CUtil::CountTally(line, cmplx_calc_list, cnt, 1, exclude, "", "", &result->cmplx_calc_count, casesensitive);
result->cmplx_calc_lines += cnt;
// conditionals
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Conditionals" );
CUtil::CountTally(line, cmplx_cond_list, cnt, 1, exclude, "", "", &result->cmplx_cond_count, casesensitive);
result->cmplx_cond_lines += cnt;
//tmpc = (int)CUtil::FindKeyword( line, "END-IF" );
//result->cmplx_cond_lines = 0;
// logical operators
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Logical" );
CUtil::CountTally(line, cmplx_logic_list, cnt, 1, exclude, "", "", &result->cmplx_logic_count, casesensitive);
result->cmplx_logic_lines += cnt;
// preprocessor directives
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Preprocessor" );
CUtil::CountTally(line, cmplx_preproc_list, cnt, 1, exclude, "", "", &result->cmplx_preproc_count, casesensitive);
result->cmplx_preproc_lines += cnt;
// assignments
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Assignments" );
CUtil::CountTally(line, cmplx_assign_list, cnt, 1, exclude, "", "", &result->cmplx_assign_count, casesensitive);
result->cmplx_assign_lines += cnt;
/* Pointers not in COBOL
// pointers
cnt = 0;
SAVE_TO_2( "CUtil::CountTally Pointers" );
// Pointers are embedded syntax so there is NO exclude string or include strings
CUtil::CountTally(line, cmplx_pointer_list, cnt, 1, "", "", "", &result->cmplx_pointer_count, casesensitive);
result->cmplx_pointer_lines += cnt;
*/
// Cyclomatic Complexity keywords
//cnt = 0;
//CUtil::CountTally(line, cmplx_cyclomatic_list, cnt, 1, exclude, "", "", &result->cmplx_cyclomatic_count, casesensitive);
// search for Cyclomatic Complexity keywords
SAVE_TO_2( "CUtil::CountTally Cyclomatic Complexity" );
CUtil::CountTally(line, cmplx_cyclomatic_list, cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive);
// COBOL has Cyclomatic Complexity keywords to ignore
if ( ignore_cmplx_cyclomatic_list.size() > 0 )
{
SAVE_TO_2( "CUtil::CountTally exclude keywords" );
CUtil::CountTally( line, ignore_cmplx_cyclomatic_list, ignore_cyclomatic_cnt, 1, exclude, "", "", 0, casesensitive );
}
// COBOL has cyclomatic complexity logical keywords
SAVE_TO_2( "CUtil::CountTally complexity Logical" );
CUtil::CountTally(line, cmplx_cyclomatic_logic_list, cyclomatic_logic_cnt, 1, exclude, "", "", 0, casesensitive);
}
/*
}
catch(const std::exception& e)
{
string dumpInfo;
string what = e.what();
StackDump( dumpInfo, EXCEPTION_HANDLER_PARSER, this->parse_threadIdx, EXCEPTION_STD_EXCEPTION, what, this );
throw( e );
}
*/
return 1;
}

50
src/CCobolCounter.h

@ -0,0 +1,50 @@
//! Code counter class definition for the Cobol language.
/*!
* \file CCobolCounter.h
*
* This file contains the code counter class definition for the Cobol language.
*/
#ifndef CCobolCounter_h
#define CCobolCounter_h
#include "CCodeCounter.h"
//! Cobol code counter class.
/*!
* \class CCobolCounter
*
* Defines the Cobol code counter class.
*/
class CCobolCounter : public CCodeCounter
{
public:
CCobolCounter();
protected:
virtual int CountDirectiveSLOC( filemap* fmap, results* result, filemap* fmapBak = NULL );
virtual int LanguageSpecificProcess( filemap* fmap, results* result, filemap* fmapBak = NULL );
// virtual int ProcessComplexityMeasures( filemap* fmap, results* result );
virtual int CountComplexity( filemap* fmap, results* result );
virtual int TrimSourceLine( string& line );
virtual int TrimSequenceNumber( string& line );
virtual int TrimAreaA( string& line );
virtual int TrimIndicator( string& line );
StringVector exclude_start_keywords; //!< SLOC lines excluded from counts starting with keywords
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CCobolCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CCobolCounter(const CCobolCounter& rhs); // Declare without implementation
// Take care of warning C4626: 'CCobolCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CCobolCounter operator=(const CCobolCounter); // Declare without implementation
};
#endif

2840
src/CCodeCounter.cpp
File diff suppressed because it is too large
View File

397
src/CCodeCounter.h

@ -0,0 +1,397 @@
//! Common code counter class for sub-classing individual languages.
/*!
* \file CCodeCounter.h
*
* This file contains the common code counter class for sub-classing individual languages.
*/
#ifndef CCodeCounter_h
#define CCodeCounter_h
#include "cc_main.h"
#include "CUtil.h"
// Enable this new approach. Disabled for 2015.12 Release
//#define ENABLE_1_PASS_PARSER
//! Common code counter class.
/*!
* \class CCodeCounter
*
* Defines the common code counter class.
*/
class CCodeCounter
{
public:
CCodeCounter();
virtual ~CCodeCounter();
virtual void InitializeCounts();
virtual int CountSLOC(filemap* fmap, results* result);
bool IsSupportedFileExtension(const string &file_name);
virtual ofstream* GetOutputStream(const string &outputFileNamePrePend = "",
const string &cmd = "", bool csvOutput = false, bool legacyOutput = false);
virtual void CloseOutputStream();
//!< public Data declarations
StringVector directive; //!< Directive statement keywords
StringVector data_name_list; //!< Data statement keywords
StringVector exec_name_list; //!< Executable statement keywords
StringVector file_extension; //!< File extension
StringVector math_func_list; //!< Math functions
StringVector trig_func_list; //!< Trigonometric functions
StringVector log_func_list; //!< Logarithmic functions
StringVector cmplx_calc_list; //!< Calculations (complexity)
StringVector cmplx_cond_list; //!< Conditionals (complexity)
StringVector cmplx_logic_list; //!< Logicals (complexity)
//Modification: 2018.01 Integration starts
StringVector three_char_operator_list; //!< List of three character operators (for Halsteads volume calculations)
StringVector two_char_operator_list; //!< List of two character operators (for Halsteads volume calculations)
StringVector one_char_operator_list; //!< List of one character operators (for Halsteads volume calculations)
set<string> keyword_operators; //!< List of reserved keyword operators (for Halsteads volume calculations)
//Modification: 2018.01 Integration ends
// Auxillary meanings keywords/operators. PASCAL ex: IF/ELSE IF, REPEAT-UNTIL, WHILE, FOR, CASE OF, CASE, Database exception clause
StringVector aux_meaning_keys; //!< Cyclomatic Complexity rings keywords/Operators, OO keywords, FP keywords
UIntVector aux_meaning_vals; //!< Cyclomatic Complexity rings values, OO values, FP values
StringVector cmplx_preproc_list; //!< Preprocessor directives (complexity)
StringVector cmplx_assign_list; //!< Assignments (complexity)
StringVector cmplx_pointer_list; //!< Pointers (complexity)
StringVector cmplx_cyclomatic_list; //!< Cyclomatic complexity decision keywords (complexity) (C/C++: if, case, while, for, catch, ?)
UIntVector cmplx_cyclomatic_listVals; //!< Cyclomatic complexity decision keywords (complexity) CC ring values, OO vals, fp vals
StringVector cmplx_cyclomatic_logic_list; //!< Cyclomatic complexity logical keywords (complexity) (C/C++:
StringVector cmplx_cyclomatic_case_list; //!< Cyclomatic complexity case keywords (complexity)
StringVector cmplx_cyclomatic_default_list; //!< Cyclomatic complexity case default keywords (complexity)
StringVector cmplx_cyclomatic_switch_list; //!< Cyclomatic complexity case switch keywords (complexity)
StringVector ignore_cmplx_cyclomatic_list; //!< Cyclomatic complexity decision keywords to ignore (for example End If)
StringVector skip_cmplx_cyclomatic_file_extension_list; //!< Cyclomatic complexity file extensions to skip
UIntPairVector directive_count; //!< Count of each directive statement keyword
UIntPairVector data_name_count; //!< Count of each data statement keyword
UIntPairVector exec_name_count; //!< Count of each executable statement keyword
UIntPairVector math_func_count; //!< Count of math functions
UIntPairVector trig_func_count; //!< Count of trigonometric functions
UIntPairVector log_func_count; //!< Count of logarithmic functions
UIntPairVector cmplx_calc_count; //!< Count of calculations
UIntPairVector cmplx_cond_count; //!< Count of conditionals
UIntPairVector cmplx_logic_count; //!< Count of logicals
UIntPairVector cmplx_preproc_count; //!< Count of preprocessor directives
UIntPairVector cmplx_assign_count; //!< Count of assignments
UIntPairVector cmplx_pointer_count; //!< Count of pointers
#ifdef ENABLE_1_PASS_PARSER
bool use_1pass_parser; //!< use single pass file parse approach Modification: 2015.12
#endif
bool print_cmplx; //!< Print complexity and keyword counts
bool cc4enable; //!< Enable Cyclomatic Complexity 4 unique conditional clauses scanning Modification: 2015.12
size_t lsloc_truncate; //!< # of characters allowed in LSLOC for differencing (0=no truncation)
string language_name; //!< Counter language name
string language_version; //!< Counter language version (do not include the word version) Modification: 2015.12
//!< For C++ could be "2014", for Scala could be "2.11.5"
string language_version_authority; //!< language version authority (either the Standards body or version creator) Modification: 2015.12
//!< For C++ could be "ISO C++ Standards Committee", for Scala could be "scala.org"
ClassType classtype; //!< Language class type
unsigned int counted_files; //!< Number of files counted
unsigned int counted_dupFiles; //!< Number of duplicate files counted
unsigned int total_filesA; //!< Total number of files in baseline A
unsigned int total_filesB; //!< Total number of duplicate files in baseline B
unsigned int total_dupFilesA; //!< Total number of files in baseline A
unsigned int total_dupFilesB; //!< Total number of duplicate files in baseline B
// Support for lightweight Stack Dump Modified: 2015.12
//
// These are set directly from caller before parsing starts Modified: 2015.12
string parse_file_name;
unsigned int parse_threadIdx;
// These are set by the Parse Exception Handler Modified: 2015.12
string parse_physical_line;
string parse_physical_line_comments;
string parse_logical_line;
// All these are set during Parsing
unsigned long currentPhyLine; //!< Which Physical line in source file is being parsed, starting with 1
unsigned long currentLSrcLine; //!< Which Logical Source line in source file is being parsed, starting with 1
// Level ABOVE current Step 1 is always CountSLOC
string currentStep1; //!< What procedure is called from CountSLOC
string currentStep2; //!< What procedure or other unique code place is called from level BELOW CountSLOC
string currentStep3; //!< What step is active from level BELOW the level BELOW CountSLOC
string currentStep4; //!< What step is active from level BELOW the level BELOW/BELOW CountSLOC (if used)
string currentFunc1; //!< What procedure name at level 1 (changes slowest)
string currentFunc2; //!< What procedure name at level 2 (changes faster)
string currentFunc3; //!< What procedure name at level 3 (changes fastest)
string currentFunc4; //!< What procedure name at level 3 (changes fastest, if used)
// Line numbers are only APPROXIMATE. Captured from most recent use of a MACRO as below.
long currentCode1; //!< What line of UCC code is running as called from CountSLOC
long currentCode2; //!< What line of UCC code is running as called from BELOW CountSLOC
long currentCode3; //!< What line of UCC code is running as called from BELOW/BELOW CountSLOC
long currentCode4; //!< What line of UCC code is running as called from BELOW/BELOW/BELOW CountSLOC (if used)
// Define some helper MACRO to make saving code context easier. Support for later Stack Dump Modified: 2015.12
#define ENTER_1(msg) { currentStep1 = msg; currentCode1 = __LINE__; currentFunc1 = UCC_FUNC_NAME; }
#define ENTER_2(msg) { currentStep2 = msg; currentCode2 = __LINE__; currentFunc2 = UCC_FUNC_NAME; }
#define ENTER_3(msg) { currentStep3 = msg; currentCode3 = __LINE__; currentFunc3 = UCC_FUNC_NAME; }
#define ENTER_4(msg) { currentStep4 = msg; currentCode4 = __LINE__; currentFunc4 = UCC_FUNC_NAME; }
#define SAVE_TO_1(msg) { currentStep1 = msg; currentCode1 = __LINE__; }
#define SAVE_TO_2(msg) { currentStep2 = msg; currentCode2 = __LINE__; }
#define SAVE_TO_3(msg) { currentStep3 = msg; currentCode3 = __LINE__; }
#define SAVE_TO_4(msg) { currentStep4 = msg; currentCode4 = __LINE__; }
/*Made these public to use them in MainObject.cpp //Ext Team. Modification: 10/16*/
StringVector BlockCommentStart; //!< Block comment start character(s) (ex. /* in C++)
StringVector BlockCommentEnd; //!< Block comment end character(s) (ex. */ in C++)
StringVector LineCommentStart; //!< Single line or embedded comment character(s)
protected:
virtual void InitializeResultsCounts(results* result);
static size_t FindQuote(string const &strline, string const &QuoteStart, size_t idx_start, char QuoteEscapeFront);
virtual int ReplaceQuote(string &strline, size_t &idx_start, bool &contd, char &CurrentQuoteEnd);
virtual int PreCountProcess(filemap* /*fmap*/) { return 0; }
int CountBlankSLOC(filemap* fmap, results* result);
virtual int CountCommentsSLOC(filemap* fmap, results* result, filemap* fmapBak = NULL);
virtual int FindHalsteadsVolume(filemap, results* ) { return -1; } //Modification: 2018.05. Integration
#ifdef ENABLE_1_PASS_PARSER
//!< These support fewer passes file parsing
/*!
* \enum ParseType
*
* Enumeration of types of well known values that parsing of a language could find.
* Or types of parsing found for various reasons.
*/
enum ParseType {
PARSE_UNKNOWN = -1, // Unknown parse type, should NOT be in actual structs after parsing
BLK_COMMENT_START, // from BlockCommentStart, Block comment start character(s) (ex. /* in C++)
BLK_COMMENT_END, // from BlockCommentEnd, Block comment end character(s) (ex. */ in C++)
LINE_COMMENT_START, // from LineCommentStart, Single line or embedded comment character(s)
DIRECTIVE, // from directive, Directive (or preprocessor) statement keywords
DATA_NAME, // from data_name_list, Data statement keywords
EXEC_NAME, // from exec_name_list, Executable statement keywords
MATH_FUNC, // from math_func_list, Math functions (not Trig or Log)
TRIG_FUNC, // from trig_func_list, Trig functions
LOG_FUNC, // from log_func_list, Log functions
CMPLX_CALC, // from cmplx_calc_list, Calculations (complexity)
CMPLX_COND, // from cmplx_cond_list, Conditionals (complexity)
CMPLX_LOGIC, // from cmplx_logic_list, Logicals (complexity)
CMPLX_PREPROC, // from cmplx_preproc_list, Preprocessor directives (complexity)
CMPLX_ASSIGN, // from cmplx_assign_list, Assignments (complexity)
CMPLX_POINTER, // from cmplx_pointer_list, Pointers (complexity)
CMPLX_CYCLOMATIC, // from cmplx_cyclomatic_list, Cyclomatic complexity decision keywords (complexity)
// These are found when doing first low level parsing
IDENTIFIER, // could be a valid identifier or resolve to a keyword type (above) in later parsing
NUMBER_PART, // could be part or entire number
NUMBER_LONG, // known to be a Long
NUMBER_INT, // known to be an Integer
NUMBER_SHORT, // known to be a Short
NUMBER_FLOAT, // known to be a Float
NUMBER_DOUBLE, // known to be a Double
STRING_LITERAL, // a string that begins and ends with valid Quote symbols within a line
STRING_MULTILINE_START, // begins with valid Quote multiline symbols, end may be on following line(s)
STRING_MULTILINE_END, // ends with valid Quote multiline symbols, start may be from previous line(s)
OPEN_CURLY_BRACE, // {
CLOSE_CURLY_BRACE, // }
OPEN_SQUARE_BRACKET, // [
CLOSE_SQUARE_BRACKET, // ]
OPEN_PAREN, // (
CLOSE_PAREN, // )
LOGICAL_END, // Statement delimiter. C++ uses semicolon ; Scala semicolon is usually optional
WILDCARD, // Match any found; in import statements (or elsewhere _ for Scala) Java uses *
SCOPE_RESOLUTION, // Declare the scope on the left. C++ uses :: or . or -> (pointer later) Scala uses .
DELIM_COMMA, // Comma symbol
DLIM_BLANK, // Blank space delimiter (Scala uses intstead of Comma for example)
TYPE_PREFIX_COLON, // single Colon used to prefix a Type in Scala, maybe used for other purposes?
DOUBLE_COLON, // 2 Colon characters used to declare class members in C++ for instance
REFERENCE, // C++ uses type & Scala implies a reference?
ADDRESS_OF // C++ uses & expression Not used in Scala?
};
#endif
// Defines for bit masks for Auxillary meanings of Keywords (must be powers of 2)
//
// Flag for each Cyclomatic Complexity ring to allow parser to avoid some hard coded compares
#define CYCLOMATIC_CC1 1
#define CYCLOMATIC_CC2 2
#define CYCLOMATIC_CC3 4
#define CYCLOMATIC_CC4 8
#define CYCLOMATIC_CC_ALL (CYCLOMATIC_CC1|CYCLOMATIC_CC2|CYCLOMATIC_CC3|CYCLOMATIC_CC4)
#define CYCLOMATIC_EXCEPT_CC4 (CYCLOMATIC_CC1|CYCLOMATIC_CC2|CYCLOMATIC_CC3)
#define CYCLOMATIC_EXCEPT_CC3 (CYCLOMATIC_CC1|CYCLOMATIC_CC2|CYCLOMATIC_CC4)
// Use these to check in code if needed
#define IsCyclomaticAny(x) (CYCLOMATIC_CC_ALL&x)
#define IsCyclomatic_1(x) (CYCLOMATIC_CC1&x)
#define IsCyclomatic_2(x) (CYCLOMATIC_CC2&x)
#define IsCyclomatic_3(x) (CYCLOMATIC_CC3&x)
#define IsCyclomatic_4(x) (CYCLOMATIC_CC4&x)
#ifdef ENABLE_1_PASS_PARSER
#define IsComplexCalc(x) (COMPLEX_CALC&x)
#define IsComplexPreProc(x) (COMPLEX_PREPROC&x)
// TODO: implement OO and FP metrics
#define IS_OBJECT_ORIENTED 64
#define IS_FUNCTIONAL 128
#define USE_EXTRA_IDX (COMPLEX_CALC|COMPLEX_PREPROC)
#define UseExtraIdx(x) (USE_EXTRA_IDX&x)
//! Structure to contain well known parse keywords/symbols and types of a language
/*!
* \struct parseElement
*
* Defines a structure to contain info to help parsing a given language
*/
struct parseElement
{
parseElement( const unsigned int original_idx, const unsigned int aux_meanings, const unsigned int ext_idx,
const ParseType parse_type, const string parse_keyword )
{
idx = original_idx;
extra_idx = ext_idx;
aux = aux_meanings;
type = parse_type;
keyword = parse_keyword;
}
parseElement()
{
idx = 0;
extra_idx = 0;
aux = 0;
type = PARSE_UNKNOWN;
keyword = "";
}
unsigned int idx; //!< Index of name array that held the keyword
unsigned int extra_idx; //!< Extra Index of to do Keywords with multiple meanings
unsigned int aux; //!< Auxillary meanings such as: is Cyclomatic
ParseType type; //!< Type of element
string keyword; //!< language keyword or special symbol(s)
};
//! Vector containing a list of parseElements.
/*!
* \typedef ParseElementVector
*
* Defines a vector containing a list of parseElements.
*/
typedef vector<parseElement> ParseElementVector;
unsigned int parse_alloc_count; //!< number of elements in pe array
parseElement * pe; //!< pointer to array to search when parsing
bool pe_dup_keywords; //!< true if duplicate keywords of different types
unsigned int pe_keyword_max_size; //!< size of longest keyword string of all entries in pe
unsigned int pe_op_max_size; //!< size of longest operator string; Calc, Logic, Assign
unsigned int pe_max_idx; //!< index of end +1 of parse array
unsigned int pe_mid_idx; //!< index of mid point of parse array
string pe_mid_keyword; //!< keyword value at mid point
#endif // #ifdef ENABLE_1_PASS_PARSER
// Modification: 2015.12
virtual int CountCommentsSLOCperLine( filemap::iterator iter,
results* result,
filemap::iterator itfmBak,
bool & contd,
int & comment_type,
bool & contd_nextline,
size_t & idx_start,
size_t & idx_end,
size_t & quote_idx_start,
size_t & comment_start,
string & curBlckCmtStart,
string & curBlckCmtEnd,
bool & quote_contd,
char & CurrentQuoteEnd );
int FindCommentStart(string strline, size_t &idx_start, int &comment_type,
string &curBlckCmtStart, string &curBlckCmtEnd);
virtual int CountComplexity(filemap* fmap, results* result);
virtual bool CanProcessCyclomaticComplexity( const results* result ); // Modification: 2015.12
virtual int CountDirectiveSLOC(filemap* /*fmap*/, results* /*result*/, filemap* /*fmapBak = NULL*/) { return 0; }
virtual int LanguageSpecificProcess(filemap* fmap, results* result, filemap* fmapBak = NULL);
virtual int ParseFunctionName(const string & /*line*/, string & /*lastline*/,
filemap & /*functionStack*/, string & /*functionName*/, unsigned int & /*functionCount*/) { return 0; }
#ifdef ENABLE_1_PASS_PARSER
//!< Set up some parse helpers
int PreParseFile( const results* result );
void SetInPe( StringVector & keys, UIntVector & vals, const bool useExtraIdx );
void AddToParse( unsigned int & index,
unsigned int & max_str_size,
unsigned int & empty_string_count,
const ParseType type,
StringVector sv );
#define NO_MATCH (-1)
int FindInPe( const string value, unsigned int & match_count, ParseType & type_found, unsigned int & idx );
int FindSpecialInPe( const string value, unsigned int & match_count,
ParseType & type_found, unsigned int & original_idx, unsigned int & size_found );
//!< Do a reduced pass parse
#define NO_PARSE_DONE (-2)
int ParseFile( filemap* fmap, results* result, filemap* fmapBak );
int ParseLine( const unsigned long cur_line, filemap::iterator iter, results* result, filemap::iterator itfmBak );
unsigned int StrTok( const string input, const char * separators, StringVector & tokens );
unsigned int GetTokens( const string input, const string unchanged, ParseElementVector & parse_elements );
int UpdateKeywordCount( const ParseType type_found, const unsigned int org_idx, results* result,
unsigned int &direct_items,
unsigned int &data_items,
unsigned int &exec_items,
unsigned int &math_items,
unsigned int &trig_items,
unsigned int &logarithm_items,
unsigned int &cmplx_calc_items,
unsigned int &cmplx_cond_items,
unsigned int &cmplx_logic_items,
unsigned int &cmplx_preproc_items,
unsigned int &cmplx_assign_items,
unsigned int &cmplx_pointer_items );
#endif // #ifdef ENABLE_1_PASS_PARSER
StringVector exclude_keywords; //!< List of keywords to exclude from counts
// if language supports multiple quote marks such as javascript, you can put all of them here, ex. "\"'"
string QuoteStart; //!< Starting quotation mark(s)
string QuoteEnd; //!< Ending quotation mark(s)
bool quote_start_is_end; //!< true if the start and end single line Quote symbols are equal
string QuoteMultiStart; //!< Start of a multiline Quoted string literal
string QuoteMultiEnd; //!< End of a multiline Quoted string literal
bool quote_multi_start_is_end; //!< true if the start and end of multi line Quote symbols are equal
char QuoteEscapeFront; //!< Escape character for front quote (ex. '\' in C++)
char QuoteEscapeRear; //!< Escape character for rear quote
string ContinueLine; //!< Line continuation character(s) (ex. \\ in C++)
bool casesensitive; //!< Is language is case sensitive?
ofstream output_file; //!< Output file stream
ofstream output_file_csv; //!< Output CSV file stream
private:
// This class is NOT copied or assigned to.
// Avoid copying of this class. Avoid assignment of this class.
// Compiler will give an Error if a copy or assignment is done and those Errors do NOT happen.
// This avoids a VC++ -W4 or -Wall warning C4625, C4626
// Take care of warning C4625: 'CCodeCounter' : copy constructor could not be generated because a base class copy constructor is inaccessible
CCodeCounter(const CCodeCounter& rhs);
// Take care of warning C4626: 'CCodeCounter' : assignment operator could not be generated because a base class assignment operator is inaccessible
CCodeCounter operator=(const CCodeCounter);
};
//! Map containing a logical Language enum and a pointer to Parser class for that language.
/*!
* \typedef CounterForEachLangType
*
* Defines a map containing a list of strings.
*/
typedef map<int, CCodeCounter*> CounterForEachLangType;
#endif

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save