Просмотр исходного кода

Add support for Cache coverage.

This adds support for Cache coverage parsing. A test is added
that does a basic run of the coverage on a small bit of data.
Bill Hoffman 13 лет назад
Родитель
Сommit
7955e995ec

+ 1 - 0
Source/CMakeLists.txt

@@ -424,6 +424,7 @@ SET(CTEST_SRCS cmCTest.cxx
   CTest/cmCTestCoverageCommand.cxx
   CTest/cmCTestCoverageHandler.cxx
   CTest/cmParseMumpsCoverage.cxx
+  CTest/cmParseCacheCoverage.cxx
   CTest/cmParseGTMCoverage.cxx
   CTest/cmParsePHPCoverage.cxx
   CTest/cmCTestEmptyBinaryDirectoryCommand.cxx

+ 22 - 3
Source/CTest/cmCTestCoverageHandler.cxx

@@ -12,6 +12,7 @@
 #include "cmCTestCoverageHandler.h"
 #include "cmParsePHPCoverage.h"
 #include "cmParseGTMCoverage.h"
+#include "cmParseCacheCoverage.h"
 #include "cmCTest.h"
 #include "cmake.h"
 #include "cmMakefile.h"
@@ -391,7 +392,7 @@ int cmCTestCoverageHandler::ProcessHandler()
     {
     return error;
     }
-  file_count += this->HandleGTMCoverage(&cont);
+  file_count += this->HandleMumpsCoverage(&cont);
   error = cont.Error;
   if ( file_count < 0 )
     {
@@ -761,20 +762,38 @@ int cmCTestCoverageHandler::HandlePHPCoverage(
   return static_cast<int>(cont->TotalCoverage.size());
 }
 //----------------------------------------------------------------------
-int cmCTestCoverageHandler::HandleGTMCoverage(
+int cmCTestCoverageHandler::HandleMumpsCoverage(
   cmCTestCoverageHandlerContainer* cont)
 {
+  // try gtm coverage
   cmParseGTMCoverage cov(*cont, this->CTest);
   std::string coverageFile = this->CTest->GetBinaryDir() +
     "/gtm_coverage.mcov";
   if(cmSystemTools::FileExists(coverageFile.c_str()))
     {
     cov.ReadCoverageFile(coverageFile.c_str());
+    return static_cast<int>(cont->TotalCoverage.size());
     }
   else
     {
     cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
-               " Cannot find GTM coverage file: " << coverageFile
+               " Cannot find foobar GTM coverage file: " << coverageFile
+               << std::endl);
+    }
+  cmParseCacheCoverage ccov(*cont, this->CTest);
+  coverageFile = this->CTest->GetBinaryDir() +
+    "/cache_coverage.cmcov";
+  if(cmSystemTools::FileExists(coverageFile.c_str()))
+    {
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+               "Parsing Cache Coverage: " << coverageFile
+               << std::endl);
+    ccov.ReadCoverageFile(coverageFile.c_str());
+    }
+  else
+    {
+    cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
+               " Cannot find Cache coverage file: " << coverageFile
                << std::endl);
     }
   return static_cast<int>(cont->TotalCoverage.size());

+ 2 - 2
Source/CTest/cmCTestCoverageHandler.h

@@ -70,8 +70,8 @@ private:
 
   //! Handle coverage using xdebug php coverage
   int HandlePHPCoverage(cmCTestCoverageHandlerContainer* cont);
-  //! Handle coverage using GTM
-  int HandleGTMCoverage(cmCTestCoverageHandlerContainer* cont);
+  //! Handle coverage for mumps
+  int HandleMumpsCoverage(cmCTestCoverageHandlerContainer* cont);
 
   //! Handle coverage using Bullseye
   int HandleBullseyeCoverage(cmCTestCoverageHandlerContainer* cont);

+ 187 - 0
Source/CTest/cmParseCacheCoverage.cxx

@@ -0,0 +1,187 @@
+#include "cmStandardIncludes.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "cmSystemTools.h"
+#include "cmParseCacheCoverage.h"
+#include <cmsys/Directory.hxx>
+#include <cmsys/Glob.hxx>
+
+
+cmParseCacheCoverage::cmParseCacheCoverage(cmCTestCoverageHandlerContainer& cont,
+                                       cmCTest* ctest)
+  :cmParseMumpsCoverage(cont, ctest)
+{
+}
+
+
+bool cmParseCacheCoverage::LoadCoverageData(const char* d)
+{
+  // load all the .mcov files in the specified directory
+  cmsys::Directory dir;
+  if(!dir.Load(d))
+    {
+    return false;
+    }
+  size_t numf;
+  unsigned int i;
+  numf = dir.GetNumberOfFiles();
+  for (i = 0; i < numf; i++)
+    {
+    std::string file = dir.GetFile(i);
+    if(file != "." && file != ".."
+       && !cmSystemTools::FileIsDirectory(file.c_str()))
+      {
+      std::string path = d;
+      path += "/";
+      path += file;
+      if(cmSystemTools::GetFilenameLastExtension(path) == ".cmcov")
+        {
+        if(!this->ReadCMCovFile(path.c_str()))
+          {
+          return false;
+          }
+        }
+      }
+    }
+  return true;
+}
+
+bool cmParseCacheCoverage::SplitString(std::vector<std::string>& args,
+                                       std::string const& line)
+{
+  std::string::size_type pos1 = 0;
+  std::string::size_type pos2 = line.find(',', 0);
+  if(pos2 == std::string::npos)
+    {
+    return false;
+    }
+  std::string arg;
+  while(pos2 != std::string::npos)
+    {
+    arg = line.substr(pos1, pos2-pos1);
+    args.push_back(arg);
+    pos1 = pos2+1;
+    pos2 = line.find(',',pos1);
+    }
+  arg = line.substr(pos1);
+  args.push_back(arg);
+  return true;
+}
+
+bool cmParseCacheCoverage::ReadCMCovFile(const char* file)
+{
+  std::ifstream in(file);
+  if(!in)
+    {
+    cmCTestLog(this->CTest, ERROR_MESSAGE,
+               "Can not open : "
+               << file << "\n");
+    return false;
+    }
+  std::string line;
+  std::vector<std::string> separateLine;
+  if(!cmSystemTools::GetLineFromStream(in, line))
+    {
+    cmCTestLog(this->CTest, ERROR_MESSAGE,
+               "Empty file : "
+               << file << "  referenced in this line of cmcov data:\n"
+               "[" << line << "]\n");
+    return false;
+    }
+  separateLine.clear();
+  this->SplitString(separateLine, line);
+  if(separateLine.size() !=4 || separateLine[0] != "Routine"
+     || separateLine[1] != "Line" || separateLine[2] != "RtnLine"
+     || separateLine[3] != "Code")
+    {
+    cmCTestLog(this->CTest, ERROR_MESSAGE,
+               "Bad first line of cmcov file : "
+               << file << "  line:\n"
+               "[" << line << "]\n");
+    }
+  std::string routine;
+  std::string filepath;
+  bool foundFile = false;
+  while(cmSystemTools::GetLineFromStream(in, line))
+    {
+    // clear out line argument vector
+    separateLine.clear();
+    // parse the comma separated line
+    this->SplitString(separateLine, line);
+    // might have more because code could have a quoted , in it
+    // but we only care about the first 3 args anyway
+    if(separateLine.size() < 4)
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+                 "Bad line of cmcov file expected at least 4 found: "
+                 << separateLine.size() << " "
+                 << file << "  line:\n"
+                 "[" << line << "]\n");
+      for(std::string::size_type i = 0; i < separateLine.size(); ++i)
+        {
+        cmCTestLog(this->CTest, ERROR_MESSAGE,""
+                   << separateLine[1] << " ");
+        }
+      cmCTestLog(this->CTest, ERROR_MESSAGE, "\n");
+      return false;
+      }
+    // if we do not have a routine yet, then it should be
+    // the first argument in the vector
+    if(routine.size() == 0)
+      {
+      routine = separateLine[0];
+      // Find the full path to the file
+      if(!this->FindMumpsFile(routine, filepath))
+        {
+        cmCTestLog(this->CTest, ERROR_MESSAGE,
+                   "Could not find mumps file for routine: "
+                   << routine << "\n");
+        filepath = "";
+        continue; // move to next line
+        }
+      }
+    // if we have a routine name, check for end of routine
+    else
+      {
+      // Totals in arg 0 marks the end of a routine
+      if(separateLine[0].substr(0, 6) == "Totals")
+        {
+        routine = ""; // at the end of this routine
+        filepath = "";
+        continue; // move to next line
+        }
+      }
+    // if the file path was not found for the routine
+    // move to next line. We should have already warned
+    // after the call to FindMumpsFile that we did not find
+    // it, so don't report again to cut down on output
+    if(filepath.size() == 0)
+      {
+      continue;
+      }
+    // routine and filepath should be set at this point.
+    // see if we have visited this file before, and if not
+    // call InitializeMumpsFile
+    if( this->Coverage.TotalCoverage[filepath].size() == 0)
+      {
+      // hack, this should be done on every file, but for now
+      // just do it on the ones that have coverage at all
+      this->InitializeMumpsFile(filepath);
+      }
+    // now we are ready to set the coverage from the line of data
+    cmCTestCoverageHandlerContainer::SingleFileCoverageVector&
+      coverageVector = this->Coverage.TotalCoverage[filepath];
+    std::string::size_type linenumber = atoi(separateLine[1].c_str()) -1;
+    int count = atoi(separateLine[2].c_str());
+    if(linenumber > coverageVector.size())
+      {
+      cmCTestLog(this->CTest, ERROR_MESSAGE,
+                 "Parse error line is greater than number of lines in file: "
+                 << linenumber << " " << filepath << "\n");
+      continue; // skip setting count to avoid crash
+      }
+    // now add to count for linenumber
+    coverageVector[linenumber] += count;
+    }
+  return true;
+}

+ 40 - 0
Source/CTest/cmParseCacheCoverage.h

@@ -0,0 +1,40 @@
+/*============================================================================
+  CMake - Cross Platform Makefile Generator
+  Copyright 2000-2009 Kitware, Inc.
+
+  Distributed under the OSI-approved BSD License (the "License");
+  see accompanying file Copyright.txt for details.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even the
+  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the License for more information.
+============================================================================*/
+
+#ifndef cmParseCacheCoverage_h
+#define cmParseCacheCoverage_h
+
+#include "cmParseMumpsCoverage.h"
+
+/** \class cmParseCacheCoverage
+ * \brief Parse Cache coverage information
+ *
+ * This class is used to parse Cache coverage information for
+ * mumps.
+ */
+class cmParseCacheCoverage : public cmParseMumpsCoverage
+{
+public:
+  cmParseCacheCoverage(cmCTestCoverageHandlerContainer& cont,
+    cmCTest* ctest);
+protected:
+  // implement virtual from parent
+  bool LoadCoverageData(const char* dir);
+  // Read a single mcov file
+  bool ReadCMCovFile(const char* f);
+  // split a string based on ,
+  bool SplitString(std::vector<std::string>& args,
+                   std::string const& line);
+};
+
+
+#endif

+ 3 - 25
Source/CTest/cmParseGTMCoverage.cxx

@@ -88,36 +88,14 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
         {
         cmCTestLog(this->CTest, ERROR_MESSAGE,
                    "Can not find mumps file : "
-                   << lastroutine << "  referenced in this line of mcov data:\n"
+                   << lastroutine <<
+                   "  referenced in this line of mcov data:\n"
                    "[" << line << "]\n");
         }
       continue;
       }
     // Find the full path to the file
-    std::map<cmStdString, cmStdString>::iterator i =
-      this->RoutineToDirectory.find(routine);
-    bool found = false;
-    if(i != this->RoutineToDirectory.end())
-      {
-      filepath = i->second;
-      found = true;
-      }
-    else
-      {
-      // try some alternate names
-      const char* tryname[] = {"GUX", "GTM", "ONT", 0};
-      for(int k=0; tryname[k] != 0; k++)
-        {
-        std::string routine2 = routine + tryname[k];
-        i = this->RoutineToDirectory.find(routine2);
-        if(i != this->RoutineToDirectory.end())
-          {
-          found = true;
-          filepath = i->second;
-          break; // break out of tryname loop if found
-          }
-        }
-      }
+    bool found = this->FindMumpsFile(routine, filepath);
     if(found)
       {
       int lineoffset;

+ 28 - 0
Source/CTest/cmParseMumpsCoverage.cxx

@@ -127,3 +127,31 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
     }
   return true;
 }
+
+bool cmParseMumpsCoverage::FindMumpsFile(std::string const& routine,
+                                         std::string& filepath)
+{
+  std::map<cmStdString, cmStdString>::iterator i =
+    this->RoutineToDirectory.find(routine);
+  if(i != this->RoutineToDirectory.end())
+    {
+    filepath = i->second;
+    return true;
+    }
+  else
+    {
+    // try some alternate names
+    const char* tryname[] = {"GUX", "GTM", "ONT", 0};
+    for(int k=0; tryname[k] != 0; k++)
+      {
+      std::string routine2 = routine + tryname[k];
+      i = this->RoutineToDirectory.find(routine2);
+      if(i != this->RoutineToDirectory.end())
+        {
+        filepath = i->second;
+        return true;
+        }
+      }
+    }
+  return false;
+}

+ 3 - 0
Source/CTest/cmParseMumpsCoverage.h

@@ -40,6 +40,9 @@ protected:
   bool LoadPackages(const char* dir);
   // initialize the coverage information for a single mumps file
   void InitializeMumpsFile(std::string& file);
+  // Find mumps file for routine
+  bool FindMumpsFile(std::string const& routine,
+                     std::string& filepath);
 protected:
   std::map<cmStdString, cmStdString> RoutineToDirectory;
   cmCTestCoverageHandlerContainer& Coverage;

+ 16 - 0
Tests/CMakeLists.txt

@@ -1726,6 +1726,22 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
   set_tests_properties(CTestGTMCoverage PROPERTIES
       PASS_REGULAR_EXPRESSION
       "Process file.*XINDEX.m.*Total LOC:.*127.*Percentage Coverage: 85.83.*")
+
+  configure_file(
+     "${CMake_SOURCE_DIR}/Tests/MumpsCoverage/DartConfiguration.cache.tcl.in"
+     "${CMake_BINARY_DIR}/Testing/MumpsCacheCoverage/DartConfiguration.tcl")
+  configure_file(
+    "${CMake_SOURCE_DIR}/Tests/MumpsCoverage/cache_coverage.cmcov.in"
+    "${CMake_BINARY_DIR}/Testing/MumpsCacheCoverage/cache_coverage.cmcov")
+  file(COPY "${CMake_SOURCE_DIR}/Tests/MumpsCoverage/VistA-FOIA"
+    DESTINATION "${CMake_BINARY_DIR}/Testing/MumpsCacheCoverage")
+  add_test(NAME CTestCacheCoverage
+    WORKING_DIRECTORY  "${CMake_BINARY_DIR}/Testing/MumpsCacheCoverage"
+    COMMAND
+    ${CMAKE_CTEST_COMMAND} -T Coverage --debug)
+  set_tests_properties(CTestCacheCoverage PROPERTIES
+      PASS_REGULAR_EXPRESSION
+      "Process file.*XINDEX.m.*Total LOC:.*125.*Percentage Coverage: 85.60.*")
   # Use macro, not function so that build can still be driven by CMake 2.4.
   # After 2.6 is required, this could be a function without the extra 'set'
   # calls.

+ 304 - 0
Tests/MumpsCoverage/Accounts_ReceivableTest.cmcov

@@ -0,0 +1,304 @@
+Routine,Line,RtnLine,Code
+DDIOL,1,0,"DDIOL ;SFISC/MKO-THE LOADER ;1:53 PM  12 Sep 1995"
+,2,0," ;;22.0;VA FileMan;;Mar 30, 1999"
+,3,0," ;Per VHA Directive 10-93-142, this routine should not be modified."
+,4,0," ;"
+,5,0,"EN(A,G,FMT) ;Write the text contained in local array A or global array G"
+,6,0," ;If one string passed, use format FMT"
+,7,0," N %,Y,DINAKED"
+,8,0," S DINAKED=$$LGR^%ZOSV"
+,9,0," ;"
+,10,0," S:'$D(A) A="""""
+,11,0," I $G(A)="""",$D(A)<9,$G(FMT)="""",$G(G)'?1""^""1A.7AN,$G(G)'?1""^""1A.7AN1""("".E1"")"" Q"
+,12,0," ;"
+,13,0," G:$D(DDS) SM"
+,14,0," G:$D(DIQUIET) LD"
+,15,0," ;"
+,16,0," N F,I,S"
+,17,0," I $D(A)=1,$G(G)="""" D"
+,18,0," . S F=$S($G(FMT)]"""":FMT,1:""!"")"
+,19,0," . W @F,A"
+,20,0," ;"
+,21,0," E  I $D(A)>9 S I=0 F  S I=$O(A(I)) Q:I'=+$P(I,""E"")  D"
+,22,0," . S F=$G(A(I,""F""),""!"") S:F="""" F=""?0"""
+,23,0," . W @F,$G(A(I))"
+,24,0," ;"
+,25,0," E  S I=0 F  S I=$O(@G@(I)) Q:I'=+$P(I,""E"")  D"
+,26,0," . S S=$G(@G@(I,0),$G(@G@(I)))"
+,27,0," . S F=$G(@G@(I,""F""),""!"") S:F="""" F=""?0"""
+,28,0," . W @F,S"
+,29,0," ;"
+,30,0," I DINAKED]"""" S DINAKED=$S(DINAKED["""""""""""":$O(@DINAKED),1:$D(@DINAKED))"
+,31,0," Q"
+,32,0," ;"
+,33,0,"LD ;Load text into ^TMP"
+,34,0," N I,N,T"
+,35,0," S T=$S($G(DDIOLFLG)[""H"":""DIHELP"",1:""DIMSG"")"
+,36,0," S N=$O(^TMP(T,$J,"" ""),-1)"
+,37,0," ;"
+,38,0," I $D(A)=1,$G(G)="""" D"
+,39,0," . D LD1(A,$S($G(FMT)]"""":FMT,1:""!""))"
+,40,0," ;"
+,41,0," E  I $D(A)>9 S I=0 F  S I=$O(A(I)) Q:I'=+$P(I,""E"")  D"
+,42,0," . D LD1($G(A(I)),$G(A(I,""F""),""!""))"
+,43,0," ;"
+,44,0," E  S I=0 F  S I=$O(@G@(I)) Q:I'=+$P(I,""E"")  D"
+,45,0," . D LD1($G(@G@(I),$G(@G@(I,0))),$G(@G@(I,""F""),""!""))"
+,46,0," ;"
+,47,0," K:'N @T S:N @T=N"
+,48,0," I DINAKED]"""" S DINAKED=$S(DINAKED["""""""""""":$O(@DINAKED),1:$D(@DINAKED))"
+,49,0," Q"
+,50,0," ;"
+,51,0,"LD1(S,F) ;Load string S, with format F"
+,52,0," ;In: N and T"
+,53,0," N C,J,L"
+,54,0," S:S[$C(7) S=$TR(S,$C(7),"""")"
+,55,0," F J=1:1:$L(F,""!"")-1 S N=N+1,^TMP(T,$J,N)="""""
+,56,0," S:'N N=1"
+,57,0," S:F[""?"" @(""C=""_$P(F,""?"",2))"
+,58,0," S L=$G(^TMP(T,$J,N))"
+,59,0," S ^TMP(T,$J,N)=L_$J("""",$G(C)-$L(L))_S"
+,60,0," Q"
+,61,0," ;"
+,62,0,"SM ;Print text in ScreenMan's Command Area"
+,63,0," I $D(DDSID),$D(DTOUT)!$D(DUOUT) G SMQ"
+,64,0," N DDIOL"
+,65,0," S DDIOL=1"
+,66,0," ;"
+,67,0," I $D(A)=1&($G(G)="""")!($D(A)>9) D"
+,68,0," . D MSG^DDSMSG(.A,"""",$G(FMT))"
+,69,0," E  I $D(@G@(+$O(@G@(0)),0))#2 D"
+,70,0," . D WP^DDSMSG(G)"
+,71,0," E  D HLP^DDSMSG(G)"
+,72,0," ;"
+,73,0,"SMQ I DINAKED]"""" S DINAKED=$S(DINAKED["""""""""""":$O(@DINAKED),1:$D(@DINAKED))"
+,74,0," Q"
+Totals for DDIOL,,0,
+XINDEX,1,0,"XINDEX ;ISC/REL,GFT,GRK,RWF - INDEX & CROSS-REFERENCE ;08/04/08  13:19"
+,2,1," ;;7.3;TOOLKIT;**20,27,48,61,66,68,110,121,128**;Apr 25, 1995;Build 1"
+,3,0," ; Per VHA Directive 2004-038, this routine should not be modified."
+,4,1," G ^XINDX6"
+,5,107216,"SEP F I=1:1 S CH=$E(LIN,I) D QUOTE:CH=Q Q:"" ""[CH"
+,6,107216," S ARG=$E(LIN,1,I-1) S:CH="" "" I=I+1 S LIN=$E(LIN,I,999) Q"
+,7,36371,"QUOTE F I=I+1:1 S CH=$E(LIN,I) Q:CH=""""!(CH=Q)"
+,8,36371," Q:CH]""""  S ERR=6 G ^XINDX1"
+,9,0,"ALIVE ;enter here from taskman"
+,10,1," D SETUP^XINDX7 ;Get ready to process"
+,11,468,"A2 S RTN=$O(^UTILITY($J,RTN)) G ^XINDX5:RTN="""""
+,12,467," S INDLC=(RTN?1""|""1.4L.NP) D LOAD:'INDLC"
+,13,467," I $D(ZTQUEUED),$$S^%ZTLOAD S RTN=""~"",IND(""QUIT"")=1,ZTSTOP=1 G A2"
+,14,467," I 'INDDS,INDLC W !!?10,""Data Dictionaries"",! S INDDS=1"
+,15,467," D BEG"
+,16,467," G A2"
+,17,0," ;"
+,18,467,"LOAD S X=RTN,XCNP=0,DIF=""^UTILITY(""_$J_"",1,RTN,0,"" X ^%ZOSF(""TEST"") Q:'$T  X ^%ZOSF(""LOAD"") S ^UTILITY($J,1,RTN,0,0)=XCNP-1"
+,19,467," I $D(^UTILITY($J,1,RTN,0,0)) S ^UTILITY($J,1,RTN,""RSUM"")=""B""_$$SUMB^XPDRSUM($NA(^UTILITY($J,1,RTN,0)))"
+,20,467," Q"
+,21,0,"BEG ;"
+,22,467," S %=INDLC*5 W:$X+10+%>IOM ! W RTN,$J("""",10+%-$L(RTN))"
+,23,467," S (IND(""DO""),IND(""SZT""),IND(""SZC""),LABO)=0,LC=$G(^UTILITY($J,1,RTN,0,0))"
+,24,467," I LC="""" W !,"">>>Routine '"",RTN,""' not found <<<"",! Q"
+,25,467," S TXT="""",LAB=$P(^UTILITY($J,1,RTN,0,1,0),"" "") I RTN'=$P(LAB,""("") D E^XINDX1(17)"
+,26,467," I 'INDLC,LAB[""("" D E^XINDX1(55) S LAB=$P(LAB,""("")"
+,27,0," ;if M routine(not compiled template or DD) and has more than 2 lines, check lines 1 & 2"
+,28,467," I 'INDLC,LC>2 D"
+,29,467," . N LABO S LABO=1"
+,30,467," . S LIN=$G(^UTILITY($J,1,RTN,0,1,0)),TXT=1"
+,31,0," . ;check 1st line (site/dev - ) patch 128"
+,32,467," . I $P(LIN,"";"",2,4)'?.E1""/"".E.1""-"".E D E^XINDX1(62)"
+,33,467," . S LIN=$G(^UTILITY($J,1,RTN,0,2,0)),TXT=2"
+,34,0," . ;check 2nd line (;;nn.nn[TV]nn;package;.anything)"
+,35,467," . I $P(LIN,"";"",3,99)'?1.2N1"".""1.2N.1(1""T"",1""V"").2N1"";""1A.AP1"";"".E D E^XINDX1(44) ;patch 121"
+,36,467," . I $L(INP(11)) X INP(11) ;Version number check"
+,37,467," . I $L(INP(12)) X INP(12) ;Patch number check"
+,38,467,"B5 F TXT=1:1:LC S LIN=^UTILITY($J,1,RTN,0,TXT,0),LN=$L(LIN),IND(""SZT"")=IND(""SZT"")+LN+2 D LN,ST ;Process Line"
+,39,467," S LAB="""",LABO=0,TXT=0,^UTILITY($J,1,RTN,0)=IND(""SZT"")_""^""_LC_""^""_IND(""SZC"")"
+,40,467," I IND(""SZT"")>INP(""MAX""),'INDLC S ERR=35,ERR(1)=IND(""SZT"") D ^XINDX1"
+,41,467," I IND(""SZT"")-IND(""SZC"")>INP(""CMAX""),'INDLC S ERR=58,ERR(1)=IND(""SZT"")-IND(""SZC"") D ^XINDX1"
+,42,467," D POSTRTN"
+,43,467," Q"
+,44,0," ;Proccess one line, LN = Length, LIN = Line."
+,45,44620,"LN K V S (ARG,GRB,IND(""COM""),IND(""DOL""),IND(""F""))="""",X=$P(LIN,"" "")"
+,46,44620," I '$L(X) S LABO=LABO+1 G CD"
+,47,5073," S (IND(""COM""),LAB)=$P(X,""(""),ARG=$P($P(X,""("",2),"")""),LABO=0,IND(""PP"")=X?1.8E1""("".E1"")"""
+,48,5073," D:$L(ARG) NE^XINDX3 ;Process formal parameters as New list."
+,49,5073," I 'INDLC,'$$VT^XINDX2(LAB) D E^XINDX1($S(LAB=$$CASE^XINDX52(LAB):37,1:55)) ;Check for bad labels"
+,50,5073," I $D(^UTILITY($J,1,RTN,""T"",LAB)) D E^XINDX1(15) G CD ;DUP label"
+,51,5073," S ^UTILITY($J,1,RTN,""T"",LAB)="""""
+,52,44620,"CD I LN>245 D:'(LN=246&($E(RTN,1,3)=""|dd"")) E^XINDX1(19) ;patch 119"
+,53,44620," D:LIN'?1.ANP E^XINDX1(18)"
+,54,44620," S LIN=$P(LIN,"" "",2,999),IND(""LCC"")=1"
+,55,44620," I LIN="""" D E^XINDX1(42) Q  ;Blank line ;p110"
+,56,44620," S I=0 ;Watch the scope of I, counts dots"
+,57,44620," I "" .""[$E(LIN) D  S X=$L($E(LIN,1,I),""."")-1,LIN=$E(LIN,I,999)"
+,58,10770," . F I=1:1:245 Q:"". ""'[$E(LIN,I)"
+,59,10770," . Q"
+,60,0," ;check dots against Do level IND(""DO""), IND(""DOL"")=dot level"
+,61,44620," D:'I&$G(IND(""DO1"")) E^XINDX1(51) S IND(""DO1"")=0 S:'I IND(""DO"")=0"
+,62,44620," I I D:X>IND(""DO"") E^XINDX1(51) S (IND(""DO""),IND(""DOL""))=X"
+,63,0," ;Count Comment lines, skip ;; lines"
+,64,44620," I $E(LIN)="";"",$E(LIN,2)'="";"" S IND(""SZC"")=IND(""SZC"")+$L(LIN) ;p110"
+,65,0," ;Process commands on line."
+,66,116081,"EE I LIN="""" D ^XINDX2 Q"
+,67,71461," S COM=$E(LIN),GK="""",ARG="""""
+,68,71461," I COM="";"" S LIN="""" G EE ;p110"
+,69,54870," I COM="" "" S ERR=$S(LIN?1."" "":13,1:0),LIN=$S(ERR:"""",1:$E(LIN,2,999)) D:ERR ^XINDX1 G EE"
+,70,53608," D SEP"
+,71,53608," S CM=$P(ARG,"":"",1),POST=$P(ARG,"":"",2,999),IND(""COM"")=IND(""COM"")_$C(9)_COM,ERR=48"
+,72,53608," D:ARG["":""&(POST']"""") ^XINDX1 S:POST]"""" GRB=GRB_$C(9)_POST,IND(""COM"")=IND(""COM"")_"":"""
+,73,0," ;SAC now allows lowercase commands"
+,74,53608," I CM?.E1L.E S CM=$$CASE^XINDX52(CM),COM=$E(CM) ;I IND(""LCC"") S IND(""LCC"")=0 D E^XINDX1(47)"
+,75,53608," I CM="""" D E^XINDX1(21) G EE ;Missing command"
+,76,53608," S CX=$G(IND(""CMD"",CM)) I CX="""" D  G:CX="""" EE"
+,77,0," . I $E(CM)=""Z"" S CX=""^Z"" Q  ;Proccess Z commands"
+,78,0," . D E^XINDX1(1) S LIN="""" Q"
+,79,53608," S CX=$P(CX,""^"",2,9)"
+,80,53608," D SEP I '$L(LIN),CH="" "" D E^XINDX1(13) ;trailing space"
+,81,53608," I ARG="""",""CGJMORSUWX""[COM S ERR=49 G ^XINDX1"
+,82,53608," I CX>0 D E^XINDX1(CX) S CX="""""
+,83,53608," D:$L(CX) @CX S:ARG'="""" GRB=GRB_$C(9)_ARG G EE"
+,84,0,"B S ERR=25 G ^XINDX1"
+,85,0,"C S ERR=29 G ^XINDX1"
+,86,0,"D G DG1^XINDX4"
+,87,0,"E Q:ARG=""""  S ERR=7 G ^XINDX1"
+,88,1559,"F G:ARG]"""" FR^XINDX4 S IND(""F"")=1 Q"
+,89,1932,"G G DG^XINDX4"
+,90,11,"H Q:ARG'=""""  S ERR=32 G ^XINDX1"
+,91,0,"J S ERR=36,ARG="""" G ^XINDX1"
+,92,2218,"K S ERR=$S(ARG?1""("".E:22,ARG?."" "":23,1:0) D:ERR ^XINDX1"
+,93,2218," G KL^XINDX3"
+,94,259,"L G LO^XINDX4"
+,95,30,"M G S^XINDX3"
+,96,1721,"N G NE^XINDX3"
+,97,0,"O S ERR=34 D ^XINDX1,O^XINDX3 Q"
+,98,7762,"Q Q:ARG=""""  G Q^XINDX4"
+,99,85,"R S RDTIME=0 G RD^XINDX3"
+,100,17549,"S G S^XINDX3"
+,101,0,"TR Q  ;What to process. p110"
+,102,72,"U S ARG=$P(ARG,"":"") Q"
+,103,0,"V S ARG="""",ERR=20 G ^XINDX1"
+,104,4584,"W G WR^XINDX4"
+,105,220,"X G XE^XINDX4"
+,106,0,"Z S ERR=2 D ^XINDX1 G ZC^XINDX4"
+,107,0," ;"
+,108,0," ;Save off items from line."
+,109,44620,"ST S R=LAB_$S(LABO:""+""_LABO,1:"""")"
+,110,0," ;Local variable, Global, Marked Items, Naked global, Internal ref, eXternal ref., Tag ref."
+,111,44620," S LOC="""" F  S LOC=$O(V(LOC)),S="""" Q:LOC=""""  F  S S=$O(V(LOC,S)) Q:S=""""  D SET"
+,112,44620," S ^UTILITY($J,1,RTN,""COM"",TXT)=IND(""COM"")"
+,113,44620," Q"
+,114,0," ;"
+,115,85079,"SET I V(LOC,S)]"""" F %=""!"",""~"" I V(LOC,S)[%,$G(^UTILITY($J,1,RTN,LOC,S))'[% S ^(S)=$G(^(S))_%"
+,116,85079," S %=0"
+,117,86891,"SE2 S ARG=$G(^UTILITY($J,1,RTN,LOC,S,%)) I $L(ARG)>230 S %=%+1 G SE2"
+,118,85079," S ^UTILITY($J,1,RTN,LOC,S,%)=ARG_R_V(LOC,S)_"","""
+,119,85079," Q"
+,120,0," ;"
+,121,0,"POSTRTN ;Do more overall checking"
+,122,467," N V,E,T,T1,T2"
+,123,467," S T="""" ;Check for missing Labels"
+,124,467," F  S T=$O(^UTILITY($J,1,RTN,""I"",T)),T2=T Q:T=""""  S T1=$G(^(T,0)) D"
+,125,2091," . Q:$E(T2,1,2)=""@("""
+,126,2044," . S:$E(T2,1,2)=""$$"" T2=$E(T2,3,99)"
+,127,2044," . I T2]"""",'$D(^UTILITY($J,1,RTN,""T"",$P(T2,""+"",1))) D"
+,128,0," . . F I=1:1:$L(T1,"","")-1 S LAB=$P(T1,"","",I),LABO=+$P(LAB,""+"",2),LAB=$P(LAB,""+""),E=14,E(1)=T D E^XINDX1(.E)"
+,129,0," . . Q"
+,130,2044," . Q"
+,131,467," S LAB="""",LABO=0 ;Check for valid label names"
+,132,467," I 'INDLC F  S LAB=$O(^UTILITY($J,1,RTN,""T"",LAB)) Q:LAB=""""  D"
+,133,5073," . I '$$VA^XINDX2(LAB) D E^XINDX1(55) Q"
+,134,5073," . D:'$$VT^XINDX2(LAB) E^XINDX1(37)"
+,135,5073," . Q"
+,136,467," S LAB="""",LABO=0 ;Check for valid variable names."
+,137,467," F  S LAB=$O(^UTILITY($J,1,RTN,""L"",LAB)) Q:LAB=""""  D"
+,138,15909," . D VLNF^XINDX3($P(LAB,""(""))"
+,139,15909," . Q"
+,140,467," Q"
+,141,0," ;"
+,142,0,"QUICK ;Quick, Just get a routine an print the results"
+,143,0," D QUICK^XINDX6()"
+,144,0," Q"
+Totals for XINDEX,,2446443,
+XINDX1,1,0,"XINDX1 ;ISC/REL,GRK,RWF - ERROR ROUTINE ;08/05/08  13:59"
+,2,2," ;;7.3;TOOLKIT;**20,61,66,68,110,121,128**;Apr 25, 1995;Build 1"
+,3,0," ; Per VHA Directive 2004-038, this routine should not be modified."
+,4,2," G A"
+,5,0,"E(ERR) ;"
+,6,75,"A N %,%1 ;TXT is the line of the error."
+,7,75," S ERTX=LAB_$S(LABO:""+""_LABO,1:"""")_$C(9),%1=$T(ERROR+ERR),ERTX=ERTX_$S(ERR:$P(%1,"";"",4,9),1:ERR) ;p110"
+,8,75," I ERTX[""|"" F %=1:1 S ERTX=$P(ERTX,""|"")_$S($D(ERR(%)):ERR(%),1:""??"")_$P(ERTX,""|"",%+1,99) Q:ERTX'[""|"""
+,9,75,"B I $P(%1,"";"",3)]"""" D  Q:%1]""""  ;Don't flag kernel doing kernel."
+,10,0," . S %1=$P(%1,"";"",3)"
+,11,0," . F  Q:RTN[$P(%1,"","")  S %1=$P(%1,"","",2,99) ;quit if RTN[%1 or null."
+,12,0," . Q"
+,13,75," I ERR=17,$E(RTN)'=""%"",$E(LAB)=""%"" Q  ;Don't flag %RTN w/o %."
+,14,0," ;Global is Error Line,tab,error tag,tab,error text"
+,15,75," S %=$G(^UTILITY($J,1,RTN,""E"",0))+1,^(0)=%,^(%)=TXT_$C(9)_ERTX"
+,16,75," Q"
+,17,0," ;"
+,18,0," ;F = Fatal, S = Standard, W = Warning, I = Info"
+,19,0,"ERROR ;"
+,20,0,"1 ;;;F - UNDEFINED COMMAND (rest of line not checked)."
+,21,0,"2 ;;;F - Non-standard (Undefined) 'Z' command."
+,22,0,"3 ;;XTRMON;F - Undefined Function."
+,23,0,"4 ;;;F - Undefined Special Variable."
+,24,0,"5 ;;;F - Unmatched Parenthesis."
+,25,0,"6 ;;;F - Unmatched Quotation Marks."
+,26,0,"7 ;;;F - ELSE Command followed by only one space."
+,27,0,"8 ;;;F - FOR Command did not contain '='."
+,28,0,"9 ;;;I - QUIT Command followed by only one space."
+,29,0,"10 ;;;F - Unrecognized argument in SET command."
+,30,0,"11 ;;;W - Invalid local variable name."
+,31,0,"12 ;;;W - Invalid global variable name."
+,32,0,"13 ;;;W - Blank(s) at end of line."
+,33,0,"14 ;;;F - Call to missing label '|' in this routine."
+,34,0,"15 ;;;W - Duplicate label. (M57)"
+,35,0,"16 ;;;F - Error in pattern code."
+,36,0,"17 ;;;W - First line label NOT routine name."
+,37,0,"18 ;;;W - Line contains a CONTROL (non-graphic) character."
+,38,0,"19 ;;;S - Line is longer than 245 bytes."
+,39,0,"20 ;;;S - View command used."
+,40,0,"21 ;;;F - General Syntax Error."
+,41,0,"22 ;;;S - Exclusive Kill."
+,42,0,"23 ;;;S - Unargumented Kill."
+,43,0,"24 ;;;S - Kill of an unsubscripted global."
+,44,0,"25 ;;;S - Break command used."
+,45,0,"26 ;;;S - Exclusive or Unargumented NEW command."
+,46,0,"27 ;;;S - $View function used."
+,47,0,"28 ;;ZOSV,ZIS,ZT;S - Non-standard $Z special variable used."
+,48,0,"29 ;;ZIS,ZTM;S - 'Close' command should be invoked through 'D ^%ZISC'."
+,49,0,"30 ;;;S - LABEL+OFFSET syntax."
+,50,0,"31 ;;ZOSV,ZIS,ZT;S - Non-standard $Z function used."
+,51,0,"32 ;;;S - 'HALT' command should be invoked through 'G ^XUSCLEAN'."
+,52,0,"33 ;;;S - Read command doesn't have a timeout."
+,53,0,"34 ;;ZIS;S - 'OPEN' command should be invoked through ^%ZIS."
+,54,0,"35 ;;;S - Routine exceeds SACC maximum size of 20000 (|)."
+,55,0,"36 ;;ZTM;S - Should use 'TASKMAN' instead of 'JOB' command."
+,56,0,"37 ;;;F - Label is not valid."
+,57,0,"38 ;;;F - Call to this |"
+,58,0,"39 ;;ZIS,XUS,XUP;S - Kill of a protected variable (|)."
+,59,0,"40 ;;;S - Space where a command should be."
+,60,0,"41 ;;;I - Star or pound READ used."
+,61,0,"42 ;;;W - Null line (no commands or comment)."
+,62,0,"43 ;;;F - Invalid or wrong number of arguments to a function."
+,63,0,"44 ;;;S - 2nd line of routine violates the SAC."
+,64,0,"45 ;;ZT,ZIS,XUTM,XTER;S - Set to a '%' global."
+,65,0,"46 ;;;F - Quoted string not followed by a separator."
+,66,0,"47 ;;;S - Lowercase command(s) used in line."
+,67,0,"48 ;;;F - Missing argument to a command post-conditional."
+,68,0,"49 ;;;F - Command missing an argument."
+,69,0,"50 ;;ZTM;S - Extended reference."
+,70,0,"51 ;;;F - Block structure mismatch."
+,71,0,"52 ;;;F - Reference to routine '^|'. That isn't in this UCI."
+,72,0,"53 ;;;F - Bad Number."
+,73,0,"54 ;;XG;S - Access to SSVN's restricted to Kernel."
+,74,0,"55 ;;;S - Violates VA programming standards."
+,75,0,"56 ;;;S - Patch number '|' missing from second line."
+,76,0,"57 ;;;S - Lower/Mixed case Variable name used."
+,77,0,"58 ;;;S - Routine code exceeds SACC maximum size of 15000 (|)."
+,78,0,"59 ;;;F - Bad WRITE syntax."
+,79,0,"60 ;;;S - Lock missing Timeout."
+,80,0,"61 ;;;S - Non-Incremental Lock."
+,81,0,"62 ;;;S - First line of routine violates the SAC."
+,82,0,"63 ;;;F - GO or DO mismatch from block structure (M45)."
+Totals for XINDX1,,529,

+ 8 - 0
Tests/MumpsCoverage/DartConfiguration.cache.tcl.in

@@ -0,0 +1,8 @@
+# This file is configured by CMake automatically as DartConfiguration.tcl
+# If you choose not to use CMake, this file may be hand configured, by
+# filling in the required variables.
+
+
+# Configuration directories and files
+SourceDirectory: ${CMake_SOURCE_DIR}/Testing/MumpsCoverage
+BuildDirectory: ${CMake_BINARY_DIR}/Testing/MumpsCacheCoverage

+ 2 - 0
Tests/MumpsCoverage/cache_coverage.cmcov.in

@@ -0,0 +1,2 @@
+packages:${CMake_BINARY_DIR}/Testing/MumpsCoverage/VistA-FOIA/Packages
+coverage_dir:${CMake_SOURCE_DIR}/Tests/MumpsCoverage